/*
 ** This file is part of the ViTE project.
 **
 ** This software is governed by the CeCILL-A license under French law
 ** and abiding by the rules of distribution of free software. You can
 ** use, modify and/or redistribute the software under the terms of the
 ** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following
 ** URL: "http://www.cecill.info".
 **
 ** As a counterpart to the access to the source code and rights to copy,
 ** modify and redistribute granted by the license, users are provided
 ** only with a limited warranty and the software's author, the holder of
 ** the economic rights, and the successive licensors have only limited
 ** liability.
 **
 ** In this respect, the user's attention is drawn to the risks associated
 ** with loading, using, modifying and/or developing or reproducing the
 ** software by the user in light of its specific status of free software,
 ** that may mean that it is complicated to manipulate, and that also
 ** therefore means that it is reserved for developers and experienced
 ** professionals having in-depth computer knowledge. Users are therefore
 ** encouraged to load and test the software's suitability as regards
 ** their requirements in conditions enabling the security of their
 ** systems and/or data to be ensured and, more generally, to use and
 ** operate it in the same conditions as regards security.
 **
 ** The fact that you are presently reading this means that you have had
 ** knowledge of the CeCILL-A license and that you accept its terms.
 **
 **
 ** ViTE developers are (for version 0.* to 1.0):
 **
 **        - COULOMB Kevin
 **        - FAVERGE Mathieu
 **        - JAZEIX Johnny
 **        - LAGRASSE Olivier
 **        - MARCOUEILLE Jule
 **        - NOISETTE Pascal
 **        - REDONDY Arthur
 **        - VUCHENER Clément
 **
 */

#include <iostream>
#include <string>
#include <map>
/* -- */
#include <QButtonGroup>
#include <QHBoxLayout>
#include <QTabWidget>
#include <QWidget>
#include <QIcon>
#include <QLibrary>
#include <QDir>
#include <QVariant>
#include <QVBoxLayout>
#include <QPushButton>
/* -- */
#include "common/Session.hpp"
/* -- */
#include "trace/values/Values.hpp"
#include "trace/EntityValue.hpp"
#include "trace/EntityTypes.hpp"
#include "trace/Entitys.hpp"
#include "trace/Trace.hpp"
/* -- */
#include "interface/Interface.hpp"
/* -- */
#include "core/Core.hpp"
/* -- */
#include "plugin/Plugin.hpp"
#include "plugin/Plugin_window.hpp"

using namespace std;

Plugin_window::Plugin_window(Core *c, QWidget *parent)
    : QMainWindow(parent), _current_index(0), _plugin_directories()
{
    _layout = new QVBoxLayout();
    _tab_widget = new QTabWidget();
    _execute_button = new QPushButton("Execute");
    _layout->addWidget(_tab_widget);
    _layout->addWidget(_execute_button);

    QWidget* central_widget = new QWidget();
    central_widget->setLayout(_layout);
    setCentralWidget(central_widget);

    QIcon icon;
    icon.addPixmap(QPixmap(QString::fromUtf8(":/icon/icon/vite.png")), QIcon::Normal, QIcon::Off);
    setWindowIcon(icon);
    setWindowTitle(QObject::tr("Plugins window"));
    setMinimumSize(800, 600);
    connect(_tab_widget, SIGNAL(currentChanged(int)), this, SLOT(reload_plugin(int)));
    connect(_execute_button, SIGNAL(clicked()), this, SLOT(execute_plugin()));

    _core = c;

    Session::load_plugin_directories(_plugin_directories);

    load_shared_plugins();

    // TODO load "compulsory" plugins (stats for example)
    load_plugin("Statistics");
    // Make a link to the menu to open the good tab if possible (menu Preferences->Plugins->...) where ... is the plugin we want to load

    // mainWindow->fillPluginMenu(list<QString> names);
}

Plugin_window::~Plugin_window() {
    _plugin_directories.clear();

    for(auto & _plugin : _plugins) {
        delete _plugin;
        _plugin = nullptr;
    }
    _plugins.clear();
}

void Plugin_window::load_shared_plugins() {

    QStringList::const_iterator it;
    for (it = _plugin_directories.constBegin() ;
         it != _plugin_directories.constEnd() ;
         ++  it) {

        QDir dir(QDir::toNativeSeparators((*it))); /* directory name where plugin are stored */
        dir.setFilter(QDir::Files);

        /* Create if not exists */
        if(!dir.exists()) {
            dir.mkpath(".");
        }

        QFileInfoList list = dir.entryInfoList();

        for (const auto & fileInfo : list) {
            QString filename = fileInfo.absoluteFilePath();

            if(!QLibrary::isLibrary(filename)) {
                continue;
            }

            QLibrary current_plugin(filename);

            Plugin *(*f)() = (Plugin *(*)()) current_plugin.resolve("create");
            if(!f) {
                cerr << "Unable to load " << current_plugin.errorString().toStdString() <<endl;
            }
            else {
                Plugin *plug = f();
                add_plugin(plug);
            }
        }
    }
}

void Plugin_window::update_trace() {
    for(vector<Plugin *>::iterator it = _plugins.begin() ;
        it < _plugins.end() ;
        ++ it) {
        (*it)->clear();
        (*it)->set_trace(_core->get_trace());
    }
}

void Plugin_window::add_plugin(Plugin *plug) {
    _plugins.push_back(plug);
    _tab_widget->addTab(plug, QString::fromStdString(plug->get_name()));
    plug->set_trace(_core->get_trace());
    plug->init();
}


void Plugin_window::show() {
    reload_plugin(_current_index);
    QMainWindow::show();
}

void Plugin_window::reload_plugin(int index) {
    //_plugins[_current_index].unload();
    if(index < (int)_plugins.size()) {
        _plugins[index]->set_trace(_core->get_trace());
        _current_index = index;
    }
}

void Plugin_window::execute_plugin() {
    if(_current_index > (int)_plugins.size() || (_current_index == 0 && _plugins.size() == 0))
        return;

    _plugins[_current_index]->execute();
}

void Plugin_window::clear_plugins() {
    for(Plugin *plugin : _plugins) {
        plugin->clear();
    }
}

void Plugin_window::reload_plugins() {
    // Temporary disconnection for delete current plugins
    disconnect(_tab_widget, SIGNAL(currentChanged(int)), this, SLOT(reload_plugin(int)));
    _plugin_directories.clear();
    for(auto & _plugin : _plugins) {
        delete _plugin;
        _plugin = nullptr;
    }
    _plugins.clear();
    connect(_tab_widget, SIGNAL(currentChanged(int)), this, SLOT(reload_plugin(int)));
    Session::load_plugin_directories(_plugin_directories);
    load_shared_plugins();

    load_plugin("Statistics");
}

void Plugin_window::load_list() {
    //     QSettings settings("ViTE", "ViTE");
    //     QStringList list = settings.value("pluginsList").toStringList();
    //     for(QStringList::const_iterator i = list.begin() ; i != list.end() ; ++ i) {
    //         load_plugin((*i).toStdString());
    //     }
}

void Plugin_window::load_plugin(const string &plugin_name) {
    Plugin *plug = Plugin::new_instance(plugin_name);
    if(!plug) {
        cerr << "plugin " << plugin_name << " not found" << endl;
        return;
    }
    add_plugin(plug);

    //     // To save/add a plugin in the settings
    //     QSettings settings("ViTE", "ViTE");
    //     QStringList plugin_list = settings.value("pluginsList").toStringList();
    //     settings.setValue("recentFiles", files);
    //     plugin_list.removeAll(filename);
    //     plugin_list.prepend(filename);
    //     settings.setValue("pluginsList", files);
}
