/****************************************************************************
**
** Copyright (C) 2012 - 2014 Jolla Ltd.
** Contact: http://jolla.com/
**
** This file is part of Qt Creator.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Digia.
**
****************************************************************************/

#include "command.h"

#include <utils/hostosinfo.h>

#include <QDir>
#include <QFile>

Command::Command()
{
#ifdef NXT_DEBUG_COMMAND_LOG
    fdx = new QFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).append("/nxtssh_command_log.txt"));
    if (fdx) {
        fdx->open(QIODevice::WriteOnly | QIODevice::Append);
    }
    tsx = new QTextStream(fdx);
    if (tsx) {
        *tsx << QString("\r\n").repeated(5)
             << QString("x").repeated(80)
             << QString("\r\n").repeated(1);
        tsx->flush();
    }
#endif /* NXT_DEBUG_COMMAND_LOG */
}

Command::~Command()
{
#ifdef NXT_DEBUG_COMMAND_LOG
    if (fdx) {
        fdx->close();
        delete fdx;
    }
    if (tsx) {
        delete tsx;
    }
#endif /* NXT_DEBUG_COMMAND_LOG */
}

QString Command::sharedHomePath() const
{
    return m_sharedHomePath;
}

void Command::setSharedHomePath(const QString& path)
{
    m_sharedHomePath = QDir::fromNativeSeparators(path);
}

QString Command::targetName() const
{
    return m_targetName;
}

void Command::setTargetName(const QString& name)
{
    m_targetName = name;
}

QString Command::sharedSourcePath() const
{
    return m_sharedSourcePath;
}

void Command::setSharedSourcePath(const QString& path)
{
    m_sharedSourcePath = QDir::fromNativeSeparators(path);
}

QString Command::sharedTargetPath() const
{
    return m_sharedSourcePath;
}

void Command::setSharedTargetPath(const QString& path)
{
    m_sharedSourcePath = QDir::fromNativeSeparators(path);
}

QString Command::sdkToolsPath() const
{
    return m_toolsPath;
}

void Command::setProjectPath(const QString& path)
{
    m_projectPath =  QDir::fromNativeSeparators(path);
}

QString Command::projectPath() const
{
    return m_projectPath;
}

void Command::setSdkToolsPath(const QString& path)
{
    m_toolsPath = QDir::fromNativeSeparators(path);
}

void Command::setArguments(const QStringList &args)
{
    m_args.clear();
    foreach (const QString& arg,args)
        m_args.append(shellSafeArgument(arg));
}

QStringList Command::arguments() const
{
    return m_args;
}

void Command::setSshParameters(const QSsh::SshConnectionParameters& params)
{
    m_sshConnectionParams = params;
}

QSsh::SshConnectionParameters Command::sshParameters() const
{
    return m_sshConnectionParams;
}

QString Command::deviceName() const
{
    return m_deviceName;
}

void Command::setDeviceName(const QString& device)
{
    m_deviceName = device;
}

QString Command::shellSafeArgument(const QString &argument) const
{
    //unix style
    static QRegExp reg1(QLatin1String("^'(.*)'$"));
    //windows style
    static QRegExp reg2(QLatin1String("^\"(.*)\"$"));

    QString safeArgument = argument;

    //unquote for file exits
    if (reg1.indexIn(argument) != -1) {
        safeArgument = reg1.cap(1);
    }

    if (reg2.indexIn(argument) != -1) {
        safeArgument = reg2.cap(1);
    }

    if (QFile::exists(safeArgument)) {
        safeArgument = QDir::fromNativeSeparators(safeArgument);
        if (safeArgument.indexOf(QLatin1Char(' ')) > -1)
            safeArgument = QLatin1Char('\'') + safeArgument + QLatin1Char('\'');
        return safeArgument;
    }
    return argument;
}

QString Command::remotePathMapping(const QString& command) const
{
#ifdef NXT_DEBUG_COMMAND_LOG
    if (tsx) {
        *tsx << "remotePathMapping(\"" << command << "\");"
             << QString("\r\n").repeated(1);
    }
#endif /* NXT_DEBUG_COMMAND_LOG */

    QString result = command;
    result.prepend(QLatin1String("cd '") + QDir::currentPath() + QLatin1String("' && "));
#ifdef NXT_DEBUG_COMMAND_LOG
    if (tsx) {
        *tsx << "[0] result = \"" << result << "\";"
             << QString("\r\n").repeated(1);
    }
#endif /* NXT_DEBUG_COMMAND_LOG */

    // First replace shared home and then shared src (error prone!)
    if (!sharedHomePath().isEmpty()) {
        QDir homeDir(sharedHomePath());
        #ifdef NXT_DEBUG_COMMAND_LOG
            if (tsx) {
                *tsx << "[a] replace \"" << homeDir.canonicalPath() << "\" -> \"" << QLatin1String("/home/nxt/share/") << "\""
                     << QString("\r\n").repeated(1);
            }
        #endif /* NXT_DEBUG_COMMAND_LOG */
        result.replace(homeDir.canonicalPath(), QLatin1String("/home/nxt/share/"));
    }
#ifdef NXT_DEBUG_COMMAND_LOG
    if (tsx) {
        *tsx << "[1] result = \"" << result << "\";"
             << QString("\r\n").repeated(1);
    }
#endif /* NXT_DEBUG_COMMAND_LOG */
    if (!sharedSourcePath().isEmpty()) {
        QDir srcDir(sharedSourcePath());
        #ifdef NXT_DEBUG_COMMAND_LOG
            if (tsx) {
                *tsx << "[b] replace \"" << srcDir.canonicalPath() << "\" -> \"" << QLatin1String("/home/nxt/src1/") << "\""
                     << QString("\r\n").repeated(1);
            }
        #endif /* NXT_DEBUG_COMMAND_LOG */
        result.replace(srcDir.canonicalPath(), QLatin1String("/home/nxt/src1/"), (Utils::HostOsInfo::isWindowsHost()?Qt::CaseInsensitive:Qt::CaseSensitive));
    }
#ifdef NXT_DEBUG_COMMAND_LOG
    if (tsx) {
        *tsx << "[2] result = \"" << result << "\";"
             << QString("\r\n").repeated(1);
    }
#endif /* NXT_DEBUG_COMMAND_LOG */
    result = result.trimmed();
#ifdef NXT_DEBUG_COMMAND_LOG
    if (tsx) {
        *tsx << "[3] result = \"" << result << "\";"
             << QString("\r\n").repeated(1);
    }
#endif /* NXT_DEBUG_COMMAND_LOG */

#ifdef NXT_DEBUG_COMMAND_LOG
    if (tsx) {
        *tsx << "return \"" << result << "\";"
             << QString("\r\n").repeated(1);
        tsx->flush();
    }
#endif /* NXT_DEBUG_COMMAND_LOG */
    return result;
}

bool Command::isValid() const
{
#if 1
    QDir curDir(QDir::currentPath());
    QDir homeDir(QDir::fromNativeSeparators(QDir::cleanPath(sharedHomePath())));
    QDir srcDir(QDir::fromNativeSeparators(QDir::cleanPath(sharedSourcePath())));

    QString currentPath = curDir.canonicalPath();
    QString cleanSharedHome = homeDir.canonicalPath();
    QString cleanSharedSrc = srcDir.canonicalPath();

    if (Utils::HostOsInfo::isWindowsHost()) {
        currentPath = currentPath.toLower();
        cleanSharedHome = cleanSharedHome.toLower();
        cleanSharedSrc = cleanSharedSrc.toLower();

        currentPath = currentPath.replace("\\", "/");
        cleanSharedHome = cleanSharedHome.replace("\\", "/");
        cleanSharedSrc = cleanSharedSrc.replace("\\", "/");
    }

    if (!currentPath.startsWith(cleanSharedHome) && (sharedSourcePath().isEmpty() || !currentPath.startsWith(cleanSharedSrc))) {
#ifdef IDS_NXT_DEBUG
        QDebug debug = qDebug();
        debug.noquote();
        debug.nospace();
        debug << "\n"
              << "currentPath = " << currentPath << "\n"
              << "cleanSharedHome = " << cleanSharedHome << "\n"
              << "cleanSharedSrc = " << cleanSharedSrc << "\n"
              << "sharedSourcePath() = " << sharedSourcePath() << "\n"
              << "\n";
#endif /* IDS_NXT_DEBUG */
        QString message = QString::fromLatin1("Project ERROR: Project is outside of shared home \"%1\" and shared src \"%2\".").arg(QDir::toNativeSeparators(sharedHomePath())).arg(QDir::toNativeSeparators(sharedSourcePath()));
        fprintf(stderr, "%s", qPrintable(message));
        fflush(stderr);
        return false;
    }
#endif
    return true;
}


const QString Command::environment_setup() const
{
    return QString(Nxt::Constants::NXT_TOOLCHAIN_PATH) + "/" + QString(Nxt::Constants::NXT_TOOLCHAIN_ENVIRONMENT_SETUP);
}

const QString Command::qmake_prefix() const
{
    return QString(Nxt::Constants::NXT_TOOLCHAIN_PATH) + "/sysroots/" + QString(Nxt::Constants::NXT_TOOLCHAIN_NAME_HOST) + "/usr/bin/";
}

const QString Command::nxt_framework() const
{
    return QString(Nxt::Constants::NXT_FRAMEWORK) + "=" + QString(Nxt::Constants::NXT_FRAMEWORK_PATH);
}

