#include "software.h"

#include <regex>

#include <QDebug>
#include <QSettings>
#include <QFileInfo>
#include <QDateTime>
#include <QByteArray>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>

#ifdef Q_OS_WIN
#include "registry.h"
#endif

#include "software/softwarefilter.h"

QString Software::key() const
{
    return DisplayName + Version;
}

QString Software::getInstallDate()const
{
    return QString("%1").arg(InstallDate.toMSecsSinceEpoch());
}

QJsonObject Software::toObject() const
{
    QJsonObject officeInfo;
    officeInfo.insert("name", DisplayName);
    officeInfo.insert("version", Version);
    officeInfo.insert("authorized", IsGenuine);
    officeInfo.insert("category", Category);
    officeInfo.insert("installation_time", getInstallDate());
    officeInfo.insert("product_keys", QJsonArray::fromStringList(ProductKeys));
    return officeInfo;
}

static QMap<QString,  SoftwareHandle *> softwareHandles;

#ifdef Q_OS_WIN
QString quoteStrip(QString UninstallString)
{
    LPWSTR *szArglist;
    int nArgs;
    QString execPath;

    szArglist = CommandLineToArgvW(UninstallString.toStdWString().data(), &nArgs);
    if (NULL == szArglist) {
        qDebug() << "parse UninstallString failed";
        return "";
    }

    if (nArgs >= 1) {
        execPath = QString::fromStdWString(szArglist[0]);
    }


    LocalFree(szArglist);

    return execPath;
}
#endif

void Software::updateStatus(const SoftwareFilter &filter)
{
#ifdef Q_OS_WIN
    qDebug().noquote() << InstallDate << InstallDate.isValid() << UninstallString;
    // 631123200000 is 1990/1/1 0:0:0
    auto validMinDate = QDateTime::fromMSecsSinceEpoch(631123200000);
    // parse uninstall file path
    if (InstallDate.toMSecsSinceEpoch() < validMinDate.toMSecsSinceEpoch()) {
        auto execPath = quoteStrip(UninstallString);
        QFileInfo uninstallInfo(execPath);
        qDebug() << InstallDate.toMSecsSinceEpoch() << InstallDate.isValid() << execPath << uninstallInfo.exists();
        if (uninstallInfo.exists()) {
            InstallDate =  uninstallInfo.created();
        } else {
            QFileInfo uninstallInfo(UninstallString);
            if (uninstallInfo.exists()) {
                InstallDate =  uninstallInfo.created();
            } else {
                qWarning() << "get install date failed";
            }
        }
    }
#endif

    Category = filter.category;
    if (softwareHandles.value(filter.id)) {
        softwareHandles.value(filter.id)->updateStatus(*this);
    } else {
        IsGenuine = false;
    }
}

void Software::registerStatusHandle(const QString &id, SoftwareHandle *sh)
{
    softwareHandles.insert(id, sh);
}

#ifdef Q_OS_WIN
Software::Software(WinRegKey *regKey)
{
    for (auto key : regKey->keys()) {
        externData.insert(key, regKey->value(key));
    }

    DisplayName = externData.value(QLatin1String("DisplayName")).toString();
    Version = externData.value(QLatin1String("DisplayVersion")).toString();
    InstallLocation = externData.value(QLatin1String("InstallLocation")).toString();
    UninstallString = externData.value(QLatin1String("UninstallString")).toString();
}
#endif
