/*
** 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 
**
*/
/*!
 *\file Session.cpp
 */

#include <iostream>
/* -- */
#include <QByteArray>
#include <QStringList>
#include <QSettings>
#include <QColor>
#include <QMap>
#include <QVariant>
#include <QCoreApplication>
#include <QDir>
#include <list>
/* -- */
#include "trace/values/Value.hpp"
#include "trace/values/Color.hpp"
#include "render/Palette.hpp"
#include "common/Session.hpp"

using namespace std;

const QByteArray Session::Export::DEFAULT_STATE     = QByteArray::number(-1);

QByteArray       Session::Export::file_dialog_state = Session::Export::DEFAULT_STATE;

int    Session::Minimap::x;
int    Session::Minimap::y;
int    Session::Minimap::width;
int    Session::Minimap::height;
int    Session::Minimap::pen_size;
QColor Session::Minimap::pen_color;
QColor Session::Minimap::brush_color;
bool   Session::Minimap::is_closed;
Palette *Session::_palette = NULL;
Palette *Session::_link_types = NULL;
Palette *Session::_event_types = NULL;
bool Session::_use_palettes=false;
bool Session::_use_palettes_is_set=false;

Session::~Session() {
}



void Session::save_config_file(){
}

void Session::load_config_file(){
    QCoreApplication::setOrganizationName(ORG_NAME);
    QCoreApplication::setOrganizationDomain(ORG_DOMAIN);
    QCoreApplication::setApplicationName(APP_NAME);
}

const QStringList Session::get_recent_files() {
    QSettings settings(ORG_NAME, APP_NAME);
    return settings.value(RECENT_FILES).toStringList();
}

void Session::add_recent_file(const QString &filename) {
    QSettings settings(ORG_NAME, APP_NAME);
    QStringList files = settings.value(RECENT_FILES).toStringList();

    // We delete if the file was already call in order to be on the top of the list
    files.removeAll(filename);
    files.prepend(filename);
    while (files.size() > _MAX_NB_RECENT_FILES)
        files.removeLast();

    settings.setValue(RECENT_FILES, files);
}

void Session::clear_recent_files() {
    QSettings settings(ORG_NAME, APP_NAME);
    settings.remove(RECENT_FILES);
}

/*** Minimap ***/
void Session::save_minimap(int x, int y, int w, int h, bool hide_on_start) {
    QSettings settings(ORG_NAME, APP_NAME);
    // Doublon ?
    Session::Minimap::x         = x;
    Session::Minimap::y         = y;
    Session::Minimap::width     = w;
    Session::Minimap::height    = h;
    Session::Minimap::is_closed = hide_on_start;

    settings.setValue("minimap/x"        , x);
    settings.setValue("minimap/y"        , y);
    settings.setValue("minimap/width"    , w);
    settings.setValue("minimap/height"   , h);
    settings.setValue("minimap/is_closed", hide_on_start);
}

/*** Plugins ***/
void Session::load_plugin_directories(QStringList &list) {
    QSettings settings(ORG_NAME, APP_NAME);
    list = settings.value(PLUGIN_DIR).toStringList();

    /* We add the $HOME/.vite if not exists as a default path */
    const QString home_dir = QDir::toNativeSeparators(QDir::homePath()+"/.vite");
    if(!list.contains(home_dir)) {
        list.append(home_dir);
    }
}

void Session::update_vertical_line_setting(bool b) {
    QSettings settings(ORG_NAME, APP_NAME);
    settings.setValue(VERTICAL_LINE, b);
}

    
bool Session::get_vertical_line_setting(){
    QSettings settings(ORG_NAME, APP_NAME);
    //set 1 as the default value if not set in the file
    bool b;
    b=settings.value(VERTICAL_LINE,1).toBool();
    return b;
}

bool Session::get_hide_warnings_setting(){
    QSettings settings(ORG_NAME, APP_NAME);
    //set 0 as the default value if not set in the file
    bool b;
    b=settings.value(HIDE_WARNINGS,0).toBool();
    return b;
}

void Session::update_hide_warnings_settings(bool b) {
    QSettings settings(ORG_NAME, APP_NAME);
    settings.setValue(HIDE_WARNINGS, b);
}

void Session::update_shaded_states_setting(bool b) {
    QSettings settings(ORG_NAME, APP_NAME);
    settings.setValue(SHADED_STATE, b);
}

    
bool Session::get_shaded_states_setting(){
    QSettings settings(ORG_NAME, APP_NAME);
    //set 1 as the default value if not set in the file
    bool b;
    b=settings.value(SHADED_STATE,1).toBool();
    return b;
}
    
void Session::update_reload_type_setting(bool b){
    QSettings settings(ORG_NAME, APP_NAME);
    settings.setValue(RELOAD_TYPE, b);
}
    
bool Session::get_reload_type_setting(){
    QSettings settings(ORG_NAME, APP_NAME);
    //set 1 as the default value if not set in the file
    bool b;
    b=settings.value(RELOAD_TYPE,1).toBool();
    return b;
}


void Session::save_plugin_directories(const QStringList &list) {
    QSettings settings(ORG_NAME, APP_NAME);
    settings.setValue(PLUGIN_DIR, list);
}

/*** States color ***/
void Session::set_use_palette(const std::string type, bool use) {
    QSettings settings(ORG_NAME, APP_NAME);
    settings.setValue(QString::fromStdString(type+"/is_used"), use);
    _use_palettes=use;
}

bool Session::get_use_palette(const std::string type) {
    
    //quick way, if we use the palettes, we don't need to check each time that we use them in the settings file, only the first time
    if(_use_palettes_is_set)return _use_palettes;
    else {
        QSettings settings(ORG_NAME, APP_NAME);
        _use_palettes=settings.value(QString::fromStdString(type+"/is_used")).toBool();
        _use_palettes_is_set=true;
        return _use_palettes;
    }
}

std::string Session::get_current_palette(const std::string type) {
    QSettings settings(ORG_NAME, APP_NAME);
    std::string tmp = settings.value(QString::fromStdString(type+CUR_PALETTE)).toString().toStdString();
    if(tmp == "")
        tmp = "default";
    return tmp;
}

void Session::set_current_palette(const std::string type, const std::string &name) {
    QSettings settings(ORG_NAME, APP_NAME);
    settings.setValue(QString::fromStdString(type+CUR_PALETTE), QString::fromStdString(name));
}

void Session::get_palettes_name(const std::string type, QStringList &list) {
    QSettings settings(ORG_NAME, APP_NAME);
    list = settings.value(QString::fromStdString(type+PALETTE_NAMES)).toStringList();
    if(!list.contains("default")) {
        list.append("default");
    }
}

Palette *Session::get_palette(const std::string type, const std::string &palette_name) {
    QSettings settings(ORG_NAME, APP_NAME);
    QMap <QString, QVariant> qmap = settings.value(QString::fromStdString(type+"/"+palette_name+"/map")).toMap();
    
    Palette *p, **where_from;
    if(type=="palette") {p = _palette; where_from = &_palette;}
    else if(type=="link_types") { p=_link_types; where_from = &_link_types;}
    else if(type=="event_types") { p=_event_types; where_from = &_event_types;}

    if(!p || p->get_name() != palette_name) {
        delete p;
        p = new Palette(string(type+"/"+palette_name));
        *where_from = p;
        for(QMap<QString, QVariant>::const_iterator it = qmap.begin() ;
            it != qmap.end() ; ++ it) {
            const QColor qc = it.value().value<QColor>();
            Color c = Color(qc.red()/255., qc.green()/255., qc.blue()/255.);
            p->add_state(it.key().toStdString(), c, qc.alpha()==255.);
        }
    }
    return p;
}


void Session::create_palette(const std::string type, const std::string &name) {
    QSettings settings(ORG_NAME, APP_NAME);
    QStringList list = settings.value(QString::fromStdString(type+PALETTE_NAMES)).toStringList();
    list.append(QString::fromStdString(name));
    settings.setValue(QString::fromStdString(type+PALETTE_NAMES), list);
}

void Session::remove_palette(const std::string type, const std::string &name) {
    QSettings settings(ORG_NAME, APP_NAME);
    QStringList list = settings.value(QString::fromStdString(type+PALETTE_NAMES)).toStringList();
    list.removeOne(QString::fromStdString(name));
    settings.setValue(QString::fromStdString(type+PALETTE_NAMES), list);
    
    QString _name = QString::fromStdString(type+"/"+name+"/map");
    settings.setValue(_name, QMap <QString, QVariant>());
}

void Session::copy_palette(const std::string type, const std::string &src, const std::string &dest) {
    QSettings settings(ORG_NAME, APP_NAME);
    // Save the palette
    QStringList list = settings.value(QString::fromStdString(type+PALETTE_NAMES)).toStringList();
    list.append(QString::fromStdString(dest));
    settings.setValue(QString::fromStdString(type+PALETTE_NAMES), list);

    // Copy the states
    QString name_src = QString::fromStdString(type+"/"+src+"/map");
    QString name_dest = QString::fromStdString(type+"/"+dest+"/map");

    QMap <QString, QVariant> qmap = settings.value(name_src).toMap();

    settings.setValue(name_dest, qmap);

}

void Session::add_state_to_palette(const std::string type, const std::string &palette_name, const std::string &state_name, const Color &c, bool visible) {

    QSettings settings(ORG_NAME, APP_NAME);
    QString name = QString::fromStdString(type+"/"+palette_name+"/map");
    QMap <QString, QVariant> qmap = settings.value(name).toMap();
    qmap[QString::fromStdString(state_name)] = QColor((int)(c.get_red()*255), (int)(c.get_green()*255), (int)(c.get_blue()*255), visible==true?255:0);

    settings.setValue(name, qmap);
}

void Session::remove_state_to_palette(const std::string type, const std::string &palette_name, const std::string &state_name) {
    QSettings settings(ORG_NAME, APP_NAME);
    QString name = QString::fromStdString(type+"/"+palette_name+"/map");
    QMap <QString, QVariant> qmap = settings.value(name).toMap();
    qmap.remove(QString::fromStdString(state_name));
    settings.setValue(name, qmap);
}


