#include "activatorcontrol.h"

#include <QTimer>
#include <QBuffer>
#include <QFile>
#include <QCoreApplication>
#include <QDBusInterface>
#include <QDBusPendingCall>
#include <QSystemTrayIcon>

#include <DWidgetUtil>
#include <DHiDPIHelper>

#include "activatorwindow.h"
#include "licensewindow.h"

#include "licensehelper.h"

static QMap<QString, SystemType> getSystemType()
{
    QMap<QString, SystemType> systemTpyeMap;
    systemTpyeMap.insert("Y2016E0001", Desktop);
    systemTpyeMap.insert("Y2016E0002", Server);
    systemTpyeMap.insert("Y2017E0001", Desktop);
    systemTpyeMap.insert("Y2017E0002", Desktop);
    systemTpyeMap.insert("Y2017E003", Desktop);
    systemTpyeMap.insert("Y2017E0003", Desktop);
    systemTpyeMap.insert("Y2017E0004", Desktop);
    systemTpyeMap.insert("Y2017E0005", Desktop);
    return systemTpyeMap;
}

static QString getLocaleEdition(const QString &edition)
{
    QMap<QString, QString> localeEditionMap;
    localeEditionMap.insert("Y2016E0001", QObject::tr("Professional Desktop"));
    localeEditionMap.insert("Y2016E0002", QObject::tr("Professional Server"));
    localeEditionMap.insert("Y2017E0001", QObject::tr("Deepin Professional V15", "Y2017E0001"));
    localeEditionMap.insert("Y2017E0002", QObject::tr("Deepin Professional V15", "Y2017E0002"));
    localeEditionMap.insert("Y2017E003", QObject::tr("Deepin Professional V15 (Education OEM)", "Y2017E003"));
    localeEditionMap.insert("Y2017E0003", QObject::tr("Deepin Professional V15 (Education OEM)", "Y2017E0003"));
    localeEditionMap.insert("Y2017E0004", QObject::tr("Deepin Education", "Y2017E0004"));
    localeEditionMap.insert("Y2017E0005", QObject::tr("Deepin Office", "Y2017E0005"));
    return localeEditionMap.value(edition);
}

static QString getLocaleCopyright(const QString &copyright)
{
    QMap<QString, QString> localeCopyrightMap;
    localeCopyrightMap.insert("Y2016CR0001", QObject::tr("Deepin Desktop"));
    localeCopyrightMap.insert("Y2016CR0002", QObject::tr("Deepin Server Operating System"));
    localeCopyrightMap.insert("Y2016CR0003", QObject::tr("Deepin General Operating System"));
    localeCopyrightMap.insert("Y2016CR0004", QObject::tr("deepin"));
    localeCopyrightMap.insert("Y2016CR0005", QObject::tr("Deepin Server"));
    localeCopyrightMap.insert("Y2016CR0006", QObject::tr("Deepin Desktop for Loongson"));
    localeCopyrightMap.insert("Y2016CR0007", QObject::tr("Deepin Server for Loongson"));
    localeCopyrightMap.insert("Y2016CR0008", QObject::tr("Deepin Desktop for Sunway"));
    localeCopyrightMap.insert("Y2016CR0009", QObject::tr("Deepin Server for Sunway"));
    return localeCopyrightMap.value(copyright);
}

class ActivatorControlPrivate
{
public:
    ActivatorControlPrivate(ActivatorControl *parent) : q_ptr(parent) {}

    ActivatorWindow     *activatorWindow    = Q_NULLPTR;
    LicenseHelper       *licenseHelper      = Q_NULLPTR;

    LicenseModel state();
    void updateTray(LicenseModel state);

    ActivatorControl *q_ptr;
    Q_DECLARE_PUBLIC(ActivatorControl)
};

ActivatorControl::ActivatorControl(QObject *parent) :
    QObject(parent), d_ptr(new ActivatorControlPrivate(this))
{
    Q_D(ActivatorControl);

    qRegisterMetaType<LicenseModel>();

    connect(this, &ActivatorControl::showActiveWindow,
    this, [ = ]() {
        if (!d->activatorWindow) {
            d->activatorWindow = new ActivatorWindow;
            d->activatorWindow->setAttribute(Qt::WA_DeleteOnClose);

            connect(d->activatorWindow, &ActivatorWindow::importLicenseFile,
                    this, &ActivatorControl::importLicenseFile);
            connect(d->activatorWindow, &ActivatorWindow::importSerialKey,
                    this, &ActivatorControl::importSerialKey);
            connect(d->activatorWindow, &ActivatorWindow::deactive,
                    this, &ActivatorControl::deactive);
            connect(d->activatorWindow, &ActivatorWindow::requestExportInformation,
                    this, &ActivatorControl::exportInformation);

            connect(this, &ActivatorControl::licenseImported,
                    d->activatorWindow, &ActivatorWindow::onLicenseImported);
            connect(this, &ActivatorControl::activeStateChanged,
                    d->activatorWindow, &ActivatorWindow::onActiveStateChanged);
            connect(this, &ActivatorControl::informationExported,
                    d->activatorWindow, &ActivatorWindow::onInformationExported);

            Q_EMIT activeStateChanged(d->state());
        }
        if (!d->activatorWindow->isVisible()) {
            d->activatorWindow->show();
            Dtk::Widget::moveToCenter(d->activatorWindow);
        }
        d->activatorWindow->activateWindow();
        d->activatorWindow->raise();
    });

    d->licenseHelper = new LicenseHelper(this);
    connect(d->licenseHelper, &LicenseHelper::activeStateChanged,
    this, [ = ]() {
        auto model = d->state();
        d->updateTray(model);
        Q_EMIT activeStateChanged(model);
    });
}

ActivatorControl::~ActivatorControl()
{

}

void ActivatorControl::exportInformation(const QString &file)
{
    Q_D(ActivatorControl);
    Q_EMIT informationExported(d->licenseHelper->exportInformation(file));
}

void ActivatorControl::importSerialKey(const QString &key)
{
    Q_D(ActivatorControl);
    auto ret = d->licenseHelper->importSerialKey(key);
    emit licenseImported(ret, d->state());
}

void ActivatorControl::importLicenseFile(const QString &filepath)
{
    Q_D(ActivatorControl);
    auto ret = d->licenseHelper->importLicenseFile(filepath);
    emit licenseImported(ret, d->state());
}

void ActivatorControl::deactive()
{
    Q_D(ActivatorControl);
    d->licenseHelper->deactive();
    emit activeStateChanged(d->state());
}

void ActivatorControl::notifyActivator()
{
    QStringList actions = QStringList() << "_open" << tr("Activate");
    QVariantMap hints;
    hints["x-deepin-action-_open"] = "dbus-send,--print-reply,--dest=com.deepin.license.activator,/com/deepin/license/activator,com.deepin.license.activator.Show";

    QList<QVariant> argumentList;
    argumentList << "deepin-activator";
    argumentList << static_cast<uint>(0);
    argumentList << "deepin-activator";
    argumentList << "";
    argumentList << tr("Your system is not activated. Please activate as soon as possible for normal use.");
    argumentList << actions;
    argumentList << hints;
    argumentList << static_cast<int>(1000);

    static QDBusInterface notifyApp("org.freedesktop.Notifications",
                                    "/org/freedesktop/Notifications", "org.freedesktop.Notifications");
    notifyApp.asyncCallWithArgumentList("Notify", argumentList);
}

void ActivatorControl::notifyCallbackAction(uint, QString)
{
    Q_EMIT showActiveWindow();
}

void ActivatorControl::Show()
{
    Q_EMIT showActiveWindow();
}

QByteArray ActivatorControl::GetIndicatorData(double /*ratio*/)
{
    Q_D(ActivatorControl);
    auto state = d->state();
    QString activeStateIconPath = ":/view/resources/red_deepin.svg";
    if (state.license.actived) {
        activeStateIconPath = ":/view/resources/green_deepin.svg";
    }

    auto iconImage = Dtk::Widget::DHiDPIHelper::loadNxPixmap(activeStateIconPath).toImage();

    QByteArray iconData;
    QBuffer buffer(&iconData);
    buffer.open(QIODevice::WriteOnly);
    iconImage.save(&buffer, "PNG");

    QTimer::singleShot(30000, [ = ]() {
        if (!d->activatorWindow) {
            qApp->exit(0);
        }
    });

    return iconData;
}

void ActivatorControl::Notify()
{
    Q_D(ActivatorControl);
    auto state = d->state();
    if (!state.license.actived) {
        notifyActivator();
    }

    QTimer::singleShot(30000, [ = ]() {
        if (!d->activatorWindow) {
            qApp->exit(0);
        }
    });
}

LicenseModel ActivatorControlPrivate::state()
{
    LicenseModel model;
    QMap<QString, SystemType> sysTypeMap = getSystemType();
    quint32 licenseState        = licenseHelper->licenseState();
    model.license.actived       = Authorized == licenseState;
    model.license.edition       = licenseHelper->edition();
    model.license.machineCode   = licenseHelper->machineCode();
    model.license.organization  = licenseHelper->organization();
    model.license.product       = licenseHelper->product();

    QString copyright = licenseHelper->systemCopyright();
    QString edition = licenseHelper->systemEdition();
    model.system.trialRemind    = licenseHelper->trialRemind();
    model.system.machineCode    = licenseHelper->systemMachinecode();
    model.system.localeCopyright = getLocaleCopyright((copyright));
    model.system.localeEdition   = getLocaleEdition((edition));
    model.system.version        = licenseHelper->systemVersion();
    model.system.systemType     = sysTypeMap.value(edition);
    return model;
}

void ActivatorControlPrivate::updateTray(LicenseModel state)
{
    QString indicatorKey = "license";
    QString activeStateIconPath(":/view/resources/red_deepin.svg");
    if (state.license.actived) {
        activeStateIconPath = QString(":/view/resources/green_deepin.svg");
    }
    auto iconImage = Dtk::Widget::DHiDPIHelper::loadNxPixmap(activeStateIconPath).toImage();
    QByteArray iconData;
    QBuffer buffer(&iconData);
    buffer.open(QIODevice::WriteOnly);
    iconImage.save(&buffer, "PNG");

    QString service =  QString("com.deepin.dde.Dock");
    QString path = QString("/com/deepin/dde/Dock/Indicator/") + indicatorKey;
    QString interface =  QString("com.deepin.dde.Dock.Indicator.") + indicatorKey;
    QTimer::singleShot(1, [ = ]() {
        QDBusInterface dockIndicatorInterface(service, path, interface);
        dockIndicatorInterface.asyncCall("setPixmapData", iconData);
    });
}
