/****************************************************************************
**
** 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 "nxtsdkkitinformation.h"

#include <nxtconstants.h>
#include <device/nxtdevicefactory.h>
#include <ui/options/nxtoptionspage.h>
#include <qtc/nxtsdkmanager.h>
#include <nxtsettings.h>

#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/projectexplorerconstants.h>

#include <QComboBox>
#include <QDir>
#include <QPushButton>

using namespace Core;
using namespace ExtensionSystem;
using namespace ProjectExplorer;
using namespace Utils;

namespace Nxt {
namespace Internal {

NxtSdkKitInformation::NxtSdkKitInformation()
{
    setId(NxtSdkKitInformation::id());
    setPriority(24);

    connect(NxtSdkManager::instance(), &NxtSdkManager::sdksUpdated, this, &NxtSdkKitInformation::onUpdated);
    connect(NxtSettings::instance(), &NxtSettings::environmentFilterChanged, this, &NxtSdkKitInformation::onUpdated);
}

QVariant NxtSdkKitInformation::defaultValue(const Kit *kit) const
{
    const NxtSdk *sdk = NxtSdkKitInformation::sdk(kit);
    if (sdk)
        return sdk->virtualMachineName();
    return QString();
}

QList<Task> NxtSdkKitInformation::validate(const Kit *kit) const
{
    if (NxtDeviceFactory::canCreate(DeviceTypeKitInformation::deviceTypeId(kit))) {
        const QString &vmName = kit->value(NxtSdkKitInformation::id()).toString();
        if (!NxtSdkManager::sdk(vmName)) {
            const QString message = QCoreApplication::translate("NxtSdk", "No valid IDS NXT Build Engine \"%1\" found").arg(vmName);
            return QList<Task>() << Task(Task::Error, message, FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
        }
    }
    return QList<Task>();
}

NxtSdk* NxtSdkKitInformation::sdk(const Kit *kit)
{
    if (!kit)
        return nullptr;
    return NxtSdkManager::sdk(kit->value(NxtSdkKitInformation::id()).toString());
}

KitInformation::ItemList NxtSdkKitInformation::toUserOutput(const Kit *kit) const
{
    if (NxtDeviceFactory::canCreate(DeviceTypeKitInformation::deviceTypeId(kit))) {
        QString vmName;
        NxtSdk* sdk = NxtSdkKitInformation::sdk(kit);
        if (sdk)
            vmName = sdk->virtualMachineName();
        return KitInformation::ItemList()
                << qMakePair(tr("IDS NXT Build Engine"), vmName);
    }
    return KitInformation::ItemList();
}

KitConfigWidget *NxtSdkKitInformation::createConfigWidget(Kit *kit) const
{
    return new NxtSdkKitInformationWidget(kit, this);
}

Core::Id NxtSdkKitInformation::id()
{
    return "Nxt.Sdk.Kit.Information";
}

void NxtSdkKitInformation::setSdk(Kit *kit, const NxtSdk* sdk)
{
    if(kit->value(NxtSdkKitInformation::id()) != sdk->virtualMachineName())
        kit->setValue(NxtSdkKitInformation::id(), sdk->virtualMachineName());
}

void NxtSdkKitInformation::addToEnvironment(const Kit *kit, Environment &env) const
{
    const NxtSdk *sdk = NxtSdkKitInformation::sdk(kit);
    if (sdk) {
        const QString sshPort = QString::number(sdk->sshPort());
        const QString sharedHome = QDir::fromNativeSeparators(sdk->sharedHomePath());
        const QString sharedTarget = QDir::fromNativeSeparators(sdk->sharedTargetsPath());
        const QString sharedSrc = QDir::fromNativeSeparators(sdk->sharedSrcPath());

        env.appendOrSet(QLatin1String(Constants::NXT_SSH_USERNAME), QLatin1String(Constants::NXT_VM_DEFAULTUSER));
        env.appendOrSet(QLatin1String(Constants::NXT_SSH_PORT), sshPort);
        env.appendOrSet(QLatin1String(Constants::NXT_SSH_PRIVATE_KEY), sdk->privateKeyFile());
        env.appendOrSet(QLatin1String(Constants::NXT_SSH_SHARED_HOME), sharedHome);
        env.appendOrSet(QLatin1String(Constants::NXT_SSH_SHARED_TARGET), sharedTarget);
        if (!sharedSrc.isEmpty())
            env.appendOrSet(QLatin1String(Constants::NXT_SSH_SHARED_SRC), sharedSrc);
        if (!NxtSettings::isEnvironmentFilterFromEnvironment() && !NxtSettings::environmentFilter().isEmpty()) {
            env.appendOrSet(QLatin1String(Constants::NXT_SDK_ENVIRONMENT_FILTER), NxtSettings::environmentFilter());
        }

        // IDS_NXT_OCEAN NXT_FRAMEWORK
        auto path = kit->value("PE.Profile.SysRoot").toString();
        env.appendOrSet(QLatin1String(Constants::NXT_FRAMEWORK), kit->value("PE.Profile.SysRoot").toString());
    }
}

void NxtSdkKitInformation::onUpdated()
{
    for (Kit *k : KitManager::kits([](const Kit *k) { return k->hasValue(NxtSdkKitInformation::id()); }))
        notifyAboutUpdate(k);
}

////////////////////////////////////////////////////////////////////////////////////////////

NxtSdkKitInformationWidget::NxtSdkKitInformationWidget(Kit *kit, const NxtSdkKitInformation *kitInformation)
    : KitConfigWidget(kit, kitInformation)
    , m_combo(new QComboBox)
    , m_manageButton(new QPushButton(tr("Manage...")))
{
    handleSdksUpdated();
    connect(m_combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &NxtSdkKitInformationWidget::handleCurrentIndexChanged);
    connect(NxtSdkManager::instance(), &NxtSdkManager::sdksUpdated, this, &NxtSdkKitInformationWidget::handleSdksUpdated);
    connect(m_manageButton, &QPushButton::clicked, this, &NxtSdkKitInformationWidget::handleManageClicked);
}

QString NxtSdkKitInformationWidget::displayName() const
{
    return tr("IDS NXT Build Engine:");
}

QString NxtSdkKitInformationWidget::toolTip() const
{
    return tr("Name of the virtual machine used as a IDS NXT Build Engine.");
}

void NxtSdkKitInformationWidget::makeReadOnly()
{
    m_combo->setEnabled(false);
}

void NxtSdkKitInformationWidget::refresh()
{
    const NxtSdk* sdk = NxtSdkKitInformation::sdk(m_kit);
    int i;
    if (sdk) {
        for (i = m_combo->count() - 1; i >= 0; --i) {
            if (sdk->virtualMachineName() == m_combo->itemText(i))
                break;
        }
    } else {
        i = 0;
    }
    m_combo->setCurrentIndex(i);
}

bool NxtSdkKitInformationWidget::visibleInKit()
{
    return NxtDeviceFactory::canCreate(DeviceTypeKitInformation::deviceTypeId(m_kit));
}

QWidget *NxtSdkKitInformationWidget::mainWidget() const
{
    return m_combo;
}

QWidget *NxtSdkKitInformationWidget::buttonWidget() const
{
    return m_manageButton;
}

void NxtSdkKitInformationWidget::handleSdksUpdated()
{
    const QList<NxtSdk*>& sdks = NxtSdkManager::sdks();
    m_combo->blockSignals(true);
    m_combo->clear();
    if(sdks.isEmpty()) {
        m_combo->addItem(tr("None"));
    } else {
        foreach (const NxtSdk *sdk, sdks) {
            m_combo->addItem(sdk->virtualMachineName());
        }
    }
    m_combo->blockSignals(false);
    refresh();
}

void NxtSdkKitInformationWidget::handleManageClicked()
{
    NxtOptionsPage *page = PluginManager::getObject<NxtOptionsPage>();
    if (page)
        page->setSdk(m_combo->currentText());
    ICore::showOptionsDialog(Constants::NXT_OPTIONS_ID);
}

void NxtSdkKitInformationWidget::handleCurrentIndexChanged()
{
    const NxtSdk* sdk = NxtSdkManager::sdk(m_combo->currentText());
    if (sdk)
        NxtSdkKitInformation::setSdk(m_kit, sdk);
}

} // namespace Internal
} // namespace Nxt
