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

#include "GUI/Support/Util/Path.h"
#include "BAVersion.h"
#include <QDateTime>
#include <QDir>
#include <QFileInfo>
#include <QMap>
#include <QModelIndex>
#include <QStandardPaths>
#include <QVector>

namespace {

QMap<QString, QString> initializeCharacterMap()
{
    QMap<QString, QString> result;
    result["\\"] = "_backslash_";
    result["/"] = "_slash_";
    result["\""] = "_quote_";
    result["<"] = "_lessthan_";
    result[">"] = "_greaterthan_";
    result["|"] = "_pipe_";
    result["?"] = "_questionmark_";
    return result;
}

const QMap<QString, QString> invalidCharacterMap = initializeCharacterMap();

} // namespace


QString GUI::Base::Path::withTildeHomePath(const QString& path)
{
#ifdef Q_OS_WIN
    return path;
#endif

    static const QString homePath = QDir::homePath();

    QFileInfo fi(QDir::cleanPath(path));
    QString outPath = fi.absoluteFilePath();
    if (outPath.startsWith(homePath))
        return QLatin1Char('~') + outPath.mid(homePath.size());
    return path;
}

QString GUI::Base::Path::getBornAgainVersionString()
{
    return QString::fromStdString(BornAgain::GetVersionNumber());
}

//! Returns valid file name to be saved on disk. This name is constructed from proposed_name
//! by replacing all special characters with text representation
//! \ backslash
//! / slash
//! " quote
//! < lessthan
//! > greaterthan
//! | pipe
//! ? questionmark
QString GUI::Base::Path::getValidFileName(const QString& proposed_name)
{
    QString result = proposed_name;
    for (auto it = invalidCharacterMap.begin(); it != invalidCharacterMap.end(); ++it)
        result.replace(it.key(), it.value());
    return result;
}

//! parses version string into 2 numbers, returns true in the case of success
bool GUI::Base::Path::parseVersion(const QString& version, int& major_num, int& minor_num)
{
    major_num = 0;
    minor_num = 0;
    bool success(true);
    QStringList nums = version.split(".");
    if (nums.size() != 2)
        return false;

    bool ok(false);
    major_num = nums.at(0).toInt(&ok);
    success &= ok;
    minor_num = nums.at(1).toInt(&ok);
    success &= ok;

    return success;
}

int GUI::Base::Path::versionCode(const QString& version)
{
    int ba_major;
    int ba_minor;
    if (!parseVersion(version, ba_major, ba_minor))
        return -1;

    return ba_major * 100 + ba_minor;
}

//! Returns true if current BornAgain version match minimal required version
bool GUI::Base::Path::isVersionMatchMinimal(const QString& version, const QString& minimal_version)
{
    return versionCode(version) >= versionCode(minimal_version);
}

//! Returns file directory from the full file path
QString GUI::Base::Path::fileDir(const QString& fileName)
{
    QFileInfo info(fileName);
    if (info.exists())
        return info.dir().path();
    return "";
}

//! Returns base name of file.

QString GUI::Base::Path::baseName(const QString& fileName)
{
    QFileInfo info(fileName);
    return info.baseName();
}

QString GUI::Base::Path::appDataFolder()
{
    return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
}

QString GUI::Base::Path::getPathFromIndex(const QModelIndex& index)
{
    if (!index.isValid())
        return "";

    QStringList namePath;
    QModelIndex cur = index;
    while (cur.isValid()) {
        namePath << cur.data().toString();
        cur = cur.parent();
    }
    std::reverse(namePath.begin(), namePath.end());
    return namePath.join("/");
}
