#ifndef NXTRUN_RESTCONFIGURATION_HIDE_CONFIGURATION_WIDGET
#define NXTRUN_RESTCONFIGURATION_HIDE_CONFIGURATION_WIDGET
#endif

#include "nxtrunrestconfiguration.h"

#include <nxtconstants.h>
#include <steps/deploy/nxtdeployconfiguration.h>

#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/deployconfiguration.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
#include <projectexplorer/runnables.h>
#include <projectexplorer/target.h>
#include <remotelinux/remotelinuxenvironmentaspect.h>

#include <QWidget>
#include <QJsonObject>
#include <QJsonDocument>

using namespace ProjectExplorer;
using namespace RemoteLinux;
using namespace Utils;

namespace Nxt {
namespace Internal {

NxtRunRestConfiguration::NxtRunRestConfiguration(Target *parent)
    : RemoteLinuxRunConfiguration(parent, Constants::NXT_RUNRESTCONFIGURATION_PREFIX)
{
    if (vappName.isEmpty()) {
        const QString buildDirectory = target()->activeBuildConfiguration()->rawBuildDirectory().toString();
        const QString projectDirectory = project()->projectDirectory().toString();
        const QString manifestFilePath = [&]() -> QString {
                QString pathInProjectDirectory = Utils::FileName::fromString(projectDirectory).appendPath("manifest.json").toString();
                QFileInfo fi(pathInProjectDirectory);
                if (fi.exists() && fi.isFile()) {
                    return pathInProjectDirectory;
                }

                QString pathInBuildDirectory = Utils::FileName::fromString(buildDirectory).appendPath("MANIFEST").toString();
                QFile file(pathInBuildDirectory);
                if (file.exists()) {
                    file.open(QIODevice::ReadOnly | QIODevice::Text);
                    const QString manifestFileName = QString::fromLocal8Bit(file.readAll()).simplified();
                    file.close();
                    return Utils::FileName::fromString(projectDirectory).appendPath(manifestFileName).toString();
                }

                return "";
        }();

        QFile manifest(manifestFilePath);
        if (manifest.exists()) {
            manifest.open(QIODevice::ReadOnly | QIODevice::Text);
            QJsonObject json = QJsonDocument::fromJson(manifest.readAll()).object();
            manifest.close();
            vappName = json.value("Name").toString();
        }
    }

    targetName = target()->project()->displayName();
    remotePath = QLatin1String("/home/root/.vapps/") + vappName + QLatin1String("/") + targetName;

    setProperty("vappName", vappName);
    setProperty("targetName", targetName);
    setProperty("projectName", projectName);
    setProperty("remotePath", remotePath);

    setAlternateRemoteExecutable(remotePath);
    setUseAlternateExecutable(true);

    connect(target(), &Target::activeDeployConfigurationChanged, this, &NxtRunRestConfiguration::updateEnabledState);
}

#ifdef NXTRUN_RESTCONFIGURATION_HIDE_CONFIGURATION_WIDGET
QWidget *NxtRunRestConfiguration::createConfigurationWidget()
{
    return new QWidget(); // hide settings
}
#endif

QString NxtRunRestConfiguration::disabledReason() const
{
    if (m_disabledReason.isEmpty())
        return RemoteLinuxRunConfiguration::disabledReason();
    else
        return m_disabledReason;
}

void NxtRunRestConfiguration::updateEnabledState()
{
#if 0
    // disable configuration
    DeployConfiguration* conf = target()->activeDeployConfiguration();
    if (target()->kit())
    {
        if (conf->id() == NxtRestDeployConfiguration::configurationId())
        {
            m_disabledReason = tr("This deployment method does not support run configuration");
            setEnabled(false);
            return;
        }
    }
#endif

    RemoteLinuxRunConfiguration::updateEnabledState();
}

#if 0
QString NxtRunRestConfiguration::defaultRemoteExecutableFilePath() const
{
    return QString("foo");
    DeployConfiguration* conf = target()->activeDeployConfiguration();
    if (!conf)
        return QString();

    QString executable = RemoteLinuxRunConfiguration::defaultRemoteExecutableFilePath();
    if (conf->id() == NxtRestDeployConfiguration::configurationId()) {
        QString projectName = target()->project()->displayName();
        return QLatin1String("1 ") +  QLatin1String("/opt/sdk/") + projectName + executable;
    }

    return executable;
}
#endif

Runnable NxtRunRestConfiguration::runnable() const
{
    auto r = RemoteLinuxRunConfiguration::runnable().as<StandardRunnable>();
    // required by qtbase not to direct logs to journald
    // for Qt < 5.4
    r.environment.appendOrSet(QLatin1String("QT_NO_JOURNALD_LOG"), QLatin1String("1"));
    // for Qt >= 5.4
    r.environment.appendOrSet(QLatin1String("QT_LOGGING_TO_CONSOLE"), QLatin1String("1"));

    DeployConfiguration* conf = target()->activeDeployConfiguration();
    QTC_ASSERT(conf, return r);

    r.executable = remotePath;

    return r;
}

bool NxtRunRestConfiguration::fromMap(const QVariantMap &map)
{
    if (!RemoteLinuxRunConfiguration::fromMap(map))
        return false;

    setDefaultDisplayName(defaultDisplayName());
    return true;
}

QString NxtRunRestConfiguration::defaultDisplayName() const
{
    if (!buildSystemTarget().isEmpty())
        //: %1 is the name of a project which is being run on Nxt device
        return tr("%1 (on IDS NXT Device via REST)").arg(buildSystemTarget());
    //: Nxt run configuration default display name
    return tr("Run on IDS NXT Device via REST");
}

} // namespace Internal
} // namespace Nxt
