/*
 *  Copyright 2013 Canonical Ltd.
 *  Copyright 2011 Wolfgang Koller - http://www.gofg.at/
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include "cordova.h"

#include <QtGui>

#include <QApplication>
#include <QQuickView>
#include <QQuickItem>
#include <QQmlContext>

Cordova::Cordova(const QDir &wwwDir, QQuickItem *item, QObject *parent)
    : QObject(parent), _item(item), _www(wwwDir),
      _config(_www.absoluteFilePath("../config.xml")) {

    qDebug() << "Work directory: " << _www.absolutePath();

    if (_config.content().contains(QRegExp("^(http://)"))) {
        _mainUrl = QString(_config.content());
    } else if (!_www.exists(_config.content())) {
        qCritical() << _config.content() << "does not exist";
    } else {
        _mainUrl = QUrl::fromLocalFile(_www.absoluteFilePath(_config.content()))
	  .toString();
    }

    qDebug() << "Main URL: " << _mainUrl;
}

void Cordova::appLoaded() {
    initPlugins();
    for (QSharedPointer<CPlugin> &plugin: _plugins) {
        plugin->onAppLoaded();
    }
}

QString Cordova::get_app_dir() {
    return _www.absolutePath();
}

struct Splash {
    double rating;
    QString path;
};

QString Cordova::getSplashscreenPath() {
    double ratio = (double)_item->width() / _item->height();

    QDir dir(get_app_dir());
    if (!dir.cd("splashscreen"))
        return "";

    QList<Splash> images;
    for (QFileInfo info: dir.entryInfoList()) {
        QImage image(info.absoluteFilePath());
        if (image.isNull())
            continue;
        Splash t;
        t.path = info.absoluteFilePath();
        t.rating = std::abs((image.width() / (double)_item->width()) * ((image.width() / image.height()) / ratio) - 1);
        images.push_back(t);
    }
    std::min_element(images.begin(), images.end(), [](Splash &f, Splash &s) {
        return f.rating < s.rating;
    });
    if (!images.empty())
      return images.first().path;
    return "";
}

const CordovaInternal::Config& Cordova::config() const {
    return _config;}


void Cordova::initPlugins() {
    static bool alreadyLoaded = false;

    if (alreadyLoaded)
      return;
    
    QList<QDir> searchPath = {get_app_dir()};

    _plugins.clear();
    for (QDir pluginsDir: searchPath) {
        for (const QString &fileName: pluginsDir.entryList(QDir::Files)) {
            QString path = pluginsDir.absoluteFilePath(fileName);
            qDebug() << "Testing" << path;

            if (!QLibrary::isLibrary(path))
                continue;

            CordovaGetPluginInstances loader = (CordovaGetPluginInstances) QLibrary::resolve(path, "cordovaGetPluginInstances");
            if (!loader) {
                qCritical() << "Missing cordovaGetPluginInstances symbol in" << path;
                continue;
            }

            auto plugins = (*loader)(this);

            for (QSharedPointer<CPlugin> plugin: plugins) {
                qDebug() << "Enable plugin" << plugin->fullName();
                emit pluginWantsToBeAdded(plugin->fullName(), plugin.data(), plugin->shortName());
            }
            _plugins += plugins;
        }
    }

    alreadyLoaded = true;
}

void Cordova::loadFinished(bool ok) {
    Q_UNUSED(ok)

    initPlugins();
}

void Cordova::execQML(const QString &src) {
    emit qmlExecNeeded(src);
}

void Cordova::execJS(const QString &js) {
    emit javaScriptExecNeeded(js);
}

QString Cordova::mainUrl() const {
    return _mainUrl;
}

QObject *Cordova::topLevelEventsReceiver() {
    return dynamic_cast<QQuickWindow*>(_item->window());
}

QQuickItem *Cordova::rootObject() {
    return _item->parentItem();
}

void Cordova::setTitle(const QString &title) {
    dynamic_cast<QQuickWindow*>(_item->window())->setTitle(title);
}

void Cordova::pushViewState(const QString &state) {
    if (_states.empty()) {
        rootObject()->setState(state);
    }
    _states.push_front(state);
}

void Cordova::popViewState(const QString &state) {
    if (!_states.removeOne(state))
        qDebug() << "WARNING: incorrect view states order";

    if (_states.empty()) {
        rootObject()->setState("main");
    } else {
        rootObject()->setState(_states.front());
    }
}
