//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/Widget/AppConfig.cpp
//! @brief     Implements class AppConfig.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2021
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "GUI/View/Widget/AppConfig.h"
#include "GUI/Model/Descriptor/ComboProperty.h"
#include "GUI/View/Base/ColorGradient.h"
#include <QDir>
#include <QSettings>
#include <QStandardPaths>
#include <qcustomplot.h>

BA_GUI_API_ std::unique_ptr<AppConfig> gApp; //!< global pointer to _the_ instance

namespace {

const QString S_AUTOSAVE = "EnableAutosave";

const QString S_DIRS = "Dirs";
const QString S_DEFAULTPROJECTPATH = "DefaultProjectPath";
const QString S_ARTIFACTEXPORTDIR = "ArtifactExportDir";
const QString S_DATAIMPORTDIR = "DataImportDir";
const QString S_SCRIPTEXPORTDIR = "ScriptExportDir";
const QString S_SCRIPTIMPORTDIR = "ScriptImportDir";
const QString S_LASTUSEDIMPORFILTER1D = "LastUsedImportFilter1D";
const QString S_LASTUSEDIMPORFILTER2D = "LastUsedImportFilter2D";

// gradient map for colormaps
const QMap<QString, QCPColorGradient> gradient_map = {
    {"Grayscale", QCPColorGradient::gpGrayscale},
    {"Hot", QCPColorGradient::gpHot},
    {"Cold", QCPColorGradient::gpCold},
    {"Night", QCPColorGradient::gpNight},
    {"Candy", QCPColorGradient::gpCandy},
    {"Geography", QCPColorGradient::gpGeography},
    {"Ion", QCPColorGradient::gpIon},
    {"Thermal", QCPColorGradient::gpThermal},
    {"Polar", QCPColorGradient::gpPolar},
    {"Spectrum", QCPColorGradient::gpSpectrum},
    {"Jet", QCPColorGradient::gpJet},
    {"Hues", QCPColorGradient::gpHues},
    {"Inferno", GUI::QCP_Color::colorGradientInferno()}};

const QString startGradient = "Inferno";

} // namespace


AppConfig::AppConfig()
{
    color_gradient_combo =
        std::make_unique<ComboProperty>(ComboProperty::fromList(::gradient_map.keys()));
    color_gradient_combo->setCurrentValue(::startGradient);

    xml_dir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
    artifact_export_dir = QDir::homePath();
    data_import_dir = QDir::homePath();
    script_export_dir = QDir::homePath();
    script_import_dir = QDir::homePath();
    // TODO replace homePath by QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) ?

    loadSettings();
}

AppConfig::~AppConfig() = default;

//! Reads settings of AppConfig from global settings.

void AppConfig::loadSettings()
{
    QSettings s;

    autosave_enabled = s.value(S_AUTOSAVE, true).toBool();

    if (s.childGroups().contains(S_DIRS)) {
        s.beginGroup(S_DIRS);

        artifact_export_dir = s.value(S_ARTIFACTEXPORTDIR, artifact_export_dir).toString();
        data_import_dir = s.value(S_DATAIMPORTDIR, data_import_dir).toString();
        script_export_dir = s.value(S_SCRIPTEXPORTDIR, script_export_dir).toString();
        script_import_dir = s.value(S_SCRIPTIMPORTDIR, script_import_dir).toString();

        import_filter_1D = s.value(S_LASTUSEDIMPORFILTER1D, "").toString();
        import_filter_2D = s.value(S_LASTUSEDIMPORFILTER2D, "").toString();

        s.endGroup();
    }
}

//! Saves settings of AppConfig in global settings.

void AppConfig::saveSettings()
{
    QSettings s;
    s.setValue(S_AUTOSAVE, autosave_enabled);

    s.beginGroup(S_DIRS);
    s.setValue(S_ARTIFACTEXPORTDIR, artifact_export_dir);
    s.setValue(S_DATAIMPORTDIR, data_import_dir);
    s.setValue(S_SCRIPTEXPORTDIR, script_export_dir);
    s.setValue(S_SCRIPTIMPORTDIR, script_import_dir);
    s.setValue(S_LASTUSEDIMPORFILTER1D, import_filter_1D);
    s.setValue(S_LASTUSEDIMPORFILTER2D, import_filter_2D);
    s.endGroup();
}

QCPColorGradient AppConfig::currentColorGradient() const
{
    return ::gradient_map.value(color_gradient_combo->currentValue());
}
