// SPDX-FileCopyrightText: 2023 g10 code Gmbh
// SPDX-Contributor: Carl Schwan <carl.schwan@gnupg.com>
// SPDX-License-Identifier: GPL-2.0-or-later

#include <QApplication>
#include <QCommandLineParser>
#include <QHttpServer>
#include <QHttpServerResponse>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
#include <QPointer>
#include <QTimer>
#include <QUuid>

#include <Libkleo/KeyCache>

#include <KAboutData>
#include <KLocalizedString>

#include "config.h"
#include "firsttimedialog.h"
#include "gpgol_client_debug.h"
#include "gpgoljs_version.h"
#include "qnam.h"
#include "utils/kuniqueservice.h"
#include "utils/systemtrayicon.h"
#include "websocketclient.h"

using namespace Qt::Literals::StringLiterals;
using namespace std::chrono;

#ifdef Q_OS_WINDOWS
#include <windows.h>
#endif

#define STARTUP_TIMING qCDebug(GPGOL_CLIENT_LOG) << "Startup timing:" << startupTimer.elapsed() << "ms:"
#define STARTUP_TRACE qCDebug(GPGOL_CLIENT_LOG) << "Startup timing:" << startupTimer.elapsed() << "ms:" << SRCNAME << __func__ << __LINE__;

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    app.setQuitOnLastWindowClosed(false);

    KLocalizedString::setApplicationDomain(QByteArrayLiteral("gpgol"));

    KAboutData about(QStringLiteral("gpgol-client"),
                     i18nc("@title:window", "GnuPG Outlook Add-in"),
                     QStringLiteral(GPGOLJS_VERSION_STRING),
                     i18nc("@info", "GPG Outlook add-in"),
                     KAboutLicense::GPL,
                     i18nc("@info:credit", "© 2023-2024 g10 Code GmbH"));

    about.setDesktopFileName(u"com.gnupg.gpgoljs"_s);
    about.setProgramLogo(QIcon::fromTheme(u"com.gnupg.gpgoljs"_s));

    about.addAuthor(i18nc("@info:credit", "Carl Schwan"), i18nc("@info:credit", "Maintainer"), u"carl.schwan@gnupg.com"_s, u"https://carlschwan.eu"_s);

    about.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails"));

    about.setOrganizationDomain("gnupg.com");
    about.setBugAddress("https://dev.gnupg.org/maniphest/task/edit/form/1/");

    QCommandLineParser parser;

    KAboutData::setApplicationData(about);

    about.setupCommandLine(&parser);
    parser.process(app);
    about.processCommandLine(&parser);

    QElapsedTimer startupTimer;
    startupTimer.start();

    STARTUP_TIMING << "Application created";
    /* Create the unique service ASAP to prevent double starts if
     * the application is started twice very quickly. */
    KUniqueService service;
    STARTUP_TIMING << "Service created";

    QObject::connect(qnam, &QNetworkAccessManager::sslErrors, qnam, [](QNetworkReply *reply, const QList<QSslError> &) {
        reply->ignoreSslErrors();
    });

#ifdef Q_OS_WINDOWS
    if (AttachConsole(ATTACH_PARENT_PROCESS)) {
        freopen("CONOUT$", "w", stdout);
        freopen("CONOUT$", "w", stderr);
    }
#endif

    const auto clientId = QUuid::createUuid().toString(QUuid::WithoutBraces);

    STARTUP_TIMING << "KeyCache creation";
    WebsocketClient::self(QUrl(u"wss://localhost:5657/"_s), clientId);
    auto keyCache = Kleo::KeyCache::mutableInstance();
    keyCache->startKeyListing();

    QPointer<FirstTimeDialog> launcher = new FirstTimeDialog;
    SystemTrayIcon systemTrayIcon(QIcon::fromTheme(u"com.gnupg.gpgoljs"_s));
    systemTrayIcon.setMainWindow(launcher);
    systemTrayIcon.show();

    QObject::connect(&WebsocketClient::self(), &WebsocketClient::stateChanged, launcher.get(), &FirstTimeDialog::slotStateChanged);
    QObject::connect(&WebsocketClient::self(), &WebsocketClient::stateChanged, &systemTrayIcon, &SystemTrayIcon::slotStateChanged);

    if (Config::self()->showLauncher()) {
        launcher->show();
    }

    return app.exec();
}
