#include "INIManager.h"
#include <QApplication>
#include <QCoreApplication>
#include <QLibrary>
#include <QDir>
#include "global_defines.h"
#ifdef Q_OS_WIN
#include <Shlobj.h>
#endif

const double Default_ZielPosition           = 0;
const double Default_GeschwindigkeitPositionierung = 1;
const double Default_Beschleunigung         = 10;
const double Default_Verzoegerung           = -10;
const double Default_RuckBeschleunigung     = 100;
const double Default_RuckVerzoegerung       = -100;

#ifdef VISU_INTERN
const char* Inifile                         = "/doc/cst/Settings/wurfablauf.ini";         //Settings INI-Datei
#endif

#ifdef VISU_EXTERN
const char* Inifile                         = "wurfablauf.ini";                           //Settings INI-Datei
#endif

//allgemeine Infos
const char* SpsLogfilePfadName              = "/doc/plc/application.log";
const char* LogfileName                     = "application.log";                //Filename des Logfiles auf PC nach Kopieren von der SPS
const char* KurvenDatenOutputFile           = "out.txt";
const char* ApplikationsName                = "Ballwurf";
const char* ApplikationPfadSPS              = "/doc/plc";
const char* MaschinenDatenInifile           = "Maschinendaten.ini";
const char* Fahrprofilfile                  = "fahrprofil.txt";

#ifdef Q_OS_WIN
class QSystemLibrary
{
public:
    explicit QSystemLibrary(const QString &libraryName)
    {
        m_libraryName = libraryName;
        m_handle = 0;
        m_didLoad = false;
    }

    explicit QSystemLibrary(const wchar_t *libraryName)
    {
        m_libraryName = QString::fromWCharArray(libraryName);
        m_handle = 0;
        m_didLoad = false;
    }

    bool load(bool onlySystemDirectory = true)
    {
        m_handle = load((const wchar_t *)m_libraryName.utf16(), onlySystemDirectory);
        m_didLoad = true;
        return (m_handle != 0);
    }

    bool isLoaded()
    {
        return (m_handle != 0);
    }

    void *resolve(const char *symbol)
    {
        if (!m_didLoad)
            load();
        if (!m_handle)
            return 0;
        return (void*)GetProcAddress(m_handle, symbol);
    }

    static void *resolve(const QString &libraryName, const char *symbol)
    {
        return QSystemLibrary(libraryName).resolve(symbol);
    }

    static Q_CORE_EXPORT HINSTANCE load(const wchar_t *lpFileName, bool onlySystemDirectory = true);

private:
    HINSTANCE m_handle;
    QString m_libraryName;
    bool m_didLoad;
};

QString storageLocation()
{
    QString result;

    QSystemLibrary library(QLatin1String("Shell32"));
    typedef HRESULT (WINAPI*SHGetFolderPathW)(HWND, INT, HANDLE, DWORD, LPTSTR);
    static SHGetFolderPathW SHGetSpecialFolderPath =
            (SHGetFolderPathW)library.resolve("SHGetFolderPathW");
    if (!SHGetSpecialFolderPath)
        return QString();

    wchar_t path[MAX_PATH];

    if (SUCCEEDED(SHGetSpecialFolderPath(NULL, CSIDL_APPDATA, NULL, 0,path))){
        result = QString::fromWCharArray(path) + "/" + ApplikationsName;
        result.replace("\\", "/");
    }
    return result;
}
#endif

INIManager::INIManager()
#ifdef VISU_INTERN
    : QSettings(Inifile, QSettings::IniFormat)
#else
#ifdef Q_OS_WIN
    : QSettings(storageLocation() + "/" + Inifile, QSettings::IniFormat)
#else
    : QSettings(Inifile, QSettings::IniFormat)
#endif
#endif
{
    initDefaultSettings();
}

INIManager::~INIManager()
{
}

void INIManager::initDefaultSettings()
{
#ifdef VISU_EXTERN
#ifdef Q_OS_WIN
    QDir dir(storageLocation());
    if(!dir.exists())
        dir.mkdir(storageLocation());
#endif
#endif
    QSettings::sync();
}

QString INIManager::iniFile()
{
#ifdef VISU_INTERN
    return Inifile;
#else
#ifdef Q_OS_WIN
    return storageLocation() + "/" + Inifile;
#else
    return Inifile;
#endif
#endif
}

QVariant INIManager::value(const QString& prefix, const QString& key, const QVariant& defaultValue)
{
    QVariant variant;

    beginGroup(prefix);
    variant = QSettings::value(key, defaultValue);
    endGroup();

    return variant;
}

void INIManager::setValue(const QString& prefix, const QString& key, const QVariant& value)
{
    beginGroup(prefix);
    QSettings::setValue(key, value);
    endGroup();
}

void INIManager::removeGroup(const QString& group)
{
    remove(group);
}

bool INIManager::contains(const QString &prefix, const QString &key)
{
    beginGroup(prefix);
    bool result = QSettings::contains(key);
    endGroup();

    return result;
}




QString INIManager::logfilePfadName()
{
#ifdef VISU_EXTERN
    return applicationDataPath() + LogfileName;
#else
    return QString("/tmp/") + LogfileName;
#endif
}

QString INIManager::applicationDataPath()
{
#ifdef VISU_EXTERN
#ifdef Q_OS_WIN
    return storageLocation() + "/";
#else
    return QApplication::applicationDirPath() + QString("/");
#endif
#else
    return ApplikationPfadSPS + QString("/");
#endif
}

InterpolatorData INIManager::interpolatorData(int nummer)
{
    InterpolatorData data;
    if(nummer<0 || nummer>9)
        return data;

    QString prefix("Wurf" + QString::number(nummer));
    data.startPosition_x = value(prefix, "Sartposition",        0.0).toDouble();
    data.startPosition_y = value(prefix, "SartpositionY",       0.0).toDouble();
    data.h1             = value(prefix, "HoeheVorwaerts",       0.5).toDouble();
    data.h2             = value(prefix, "HoeheRueckwaerts",     0.5).toDouble();
    data.n1             = value(prefix, "AnzahlVorwaerts",      5).toDouble();
    data.n2             = value(prefix, "AnzahlRueckwaerts",    5).toDouble();
    data.offset_y       = value(prefix, "SteigungVorwaerts",    0.0).toDouble();
    data.offset_y2      = value(prefix, "SteigungRueckwaerts",  0.0).toDouble();
    data.s_max          = value(prefix, "Weite",                1.7).toDouble();
    data.pause          = value(prefix, "PauseZurueck",         1.0).toDouble();
    data.zwischenpause  = value(prefix, "Zwischenpause",        0.75).toDouble();
    data.a_xmax         = value(prefix, "BeschleunigungX",      50.00).toDouble();
    data.a_ymax         = value(prefix, "BeschleunigungY",      50.00).toDouble();
    data.pauseVor         = value(prefix, "PauseStart",         1.0).toDouble();

    return data;
}

void INIManager::setInterpolatorData(int nummer, InterpolatorData data)
{
    if(nummer<0 || nummer>9)
        return;

    QString prefix("Wurf" + QString::number(nummer));
    setValue(prefix, "Sartposition", data.startPosition_x);
    setValue(prefix, "SartpositionY", data.startPosition_y);
    setValue(prefix, "HoeheVorwaerts", data.h1);
    setValue(prefix, "HoeheRueckwaerts", data.h2);
    setValue(prefix, "AnzahlVorwaerts", data.n1);
    setValue(prefix, "AnzahlRueckwaerts", data.n2);
    setValue(prefix, "SteigungVorwaerts", data.offset_y);
    setValue(prefix, "SteigungRueckwaerts", data.offset_y2);
    setValue(prefix, "Weite", data.s_max);
    setValue(prefix, "PauseZurueck", data.pause);
    setValue(prefix, "Zwischenpause", data.zwischenpause);
    setValue(prefix, "BeschleunigungX", data.a_xmax);
    setValue(prefix, "BeschleunigungY", data.a_ymax);
    setValue(prefix, "PauseStart", data.pauseVor);
}

double INIManager::pauseStart()
{
    return QSettings::value("PauseStart", 1.0).toDouble();
}

void INIManager::setPauseStart(double value)
{
    QSettings::setValue("PauseStart", value);
}

double INIManager::grundpositionX()
{
    return QSettings::value("GrundpositionX", 1.0).toDouble();
}

void INIManager::setGrundpositionX(double value)
{
    QSettings::setValue("GrundpositionX", value);
}

double INIManager::grundpositionY()
{
    return QSettings::value("GrundpositionY", 1.0).toDouble();
}

void INIManager::setGrundpositionY(double value)
{
    QSettings::setValue("GrundpositionY", value);
}

double INIManager::startPositionLooser_Y()
{
    return QSettings::value("StartPositionLooserY", 0.312).toDouble();
}

void INIManager::setStartPositionLooser_Y(double value)
{
    QSettings::setValue("StartPositionLooserY", value);
}


double INIManager::startPositionLooser_X()
{
    return QSettings::value("StartPositionLooserX", 0.8).toDouble();
}

void INIManager::setStartPositionLooser_X(double value)
{
    QSettings::setValue("StartPositionLooserX", value);
}

double INIManager::spielHoehe()
{
    return QSettings::value("SpielHoehe", 0.723).toDouble();
}

void INIManager::setSpielHoehe(double value)
{
    QSettings::setValue("SpielHoehe", value);
}


double INIManager::spielWeite()
{
    return QSettings::value("SpielWeite", 1.0).toDouble();
}

void INIManager::setSpielWeite(double value)
{
    QSettings::setValue("SpielWeite", value);
}
