/*
    test_keyresolver.cpp

    This file is part of libkleopatra's test suite.
    SPDX-FileCopyrightText: 2018 Intevation GmbH

    SPDX-License-Identifier: GPL-2.0-only
*/

#include <libkleo/formatting.h>
#include <libkleo/keycache.h>
#include <libkleo/keygroupconfig.h>
#include <libkleo/keyresolver.h>

#include <QApplication>
#include <QCommandLineParser>
#include <QDebug>
#include <QTimer>

#include <chrono>
#include <gpgme++/key.h>
using namespace std::chrono_literals;
using namespace Kleo;
using namespace GpgME;

void dumpKeys(const QMap<QString, std::vector<Key>> &keysMap)
{
    for (auto it = std::begin(keysMap); it != std::end(keysMap); ++it) {
        const auto &address = it.key();
        const auto &keys = it.value();
        qDebug() << "Address:" << address;
        qDebug() << "Keys:";
        for (const auto &key : keys) {
            qDebug() << key.primaryFingerprint();
        }
    }
}

void dumpSigKeys(const std::vector<Key> &keys)
{
    for (const auto &key : keys) {
        qDebug() << key.primaryFingerprint();
    }
}

class SignalRecipient : public QObject
{
    Q_OBJECT
public:
    explicit SignalRecipient(KeyResolver *res)
        : resolver(res)
    {
    }

    void keysResolved(bool success, bool sendUnencrypted)
    {
        if (!success) {
            qDebug() << "Canceled";
            exit(1);
        }
        const auto result = resolver->result();
        qDebug() << "Resolved Signing keys:";
        dumpSigKeys(result.signingKeys);
        qDebug() << "Resolved Encryption keys:";
        dumpKeys(result.encryptionKeys);
        qDebug() << "Send Unencrypted:" << sendUnencrypted;
        exit(0);
    }

private:
    KeyResolver *resolver;
};

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QCommandLineParser parser;
    parser.setApplicationDescription(QStringLiteral("Test KeyResolver class"));
    parser.addHelpOption();
    parser.addPositionalArgument(QStringLiteral("recipients"), QStringLiteral("Recipients to resolve"), QStringLiteral("[mailboxes]"));
    parser.addOption(QCommandLineOption({QStringLiteral("overrides"), QStringLiteral("o")},
                                        QStringLiteral("Override where format can be:\n"
                                                       "OpenPGP\n"
                                                       "SMIME\n"
                                                       "Auto"),
                                        QStringLiteral("mailbox:fpr,fpr,...[:format]")));
    parser.addOption(QCommandLineOption({QStringLiteral("sender"), QStringLiteral("s")}, QStringLiteral("Mailbox of the sender"), QStringLiteral("mailbox")));
    parser.addOption(
        QCommandLineOption({QStringLiteral("sigkeys"), QStringLiteral("k")}, QStringLiteral("Explicit signing keys"), QStringLiteral("signing key")));
    parser.addOption(QCommandLineOption({QStringLiteral("encrypt"), QStringLiteral("e")}, QStringLiteral("Only select encryption keys")));
    parser.addOption(QCommandLineOption({QStringLiteral("approval"), QStringLiteral("a")}, QStringLiteral("Always show approval dlg")));
    parser.addOption(QCommandLineOption({QStringLiteral("group-config")}, QStringLiteral("Path of group config"), QStringLiteral("groupsrc")));

    parser.process(app);

    const QStringList recps = parser.positionalArguments();

    auto cache = Kleo::KeyCache::mutableInstance();
    if (parser.isSet(QStringLiteral("group-config"))) {
        cache->setGroupConfig(std::make_shared<Kleo::KeyGroupConfig>(parser.value(QStringLiteral("group-config"))));
        cache->setGroupsEnabled(true);
    }

    KeyResolver resolver(!recps.empty(), !parser.isSet(QStringLiteral("encrypt")));
    resolver.setRecipients(recps);
    resolver.setSender(parser.value(QStringLiteral("sender")));

    QMap<Protocol, QMap<QString, QStringList>> overrides;

    for (const QString &oride : parser.values(QStringLiteral("overrides"))) {
        const QStringList split = oride.split(QLatin1Char(':'));
        Protocol fmt = UnknownProtocol;
        if (split.size() < 2 || split.size() > 3) {
            parser.showHelp(1);
        }

        if (split.size() == 3) {
            const QString fmtStr = split[2].toLower();
            if (fmtStr == QLatin1StringView("openpgp")) {
                fmt = OpenPGP;
            } else if (fmtStr == QLatin1StringView("smime")) {
                fmt = CMS;
            } else if (fmtStr == QLatin1StringView("auto")) {
                fmt = UnknownProtocol;
            } else {
                parser.showHelp(1);
            }
        }
        const QStringList fingerprints = split[1].split(QLatin1Char(','));

        auto map = overrides.value(fmt);
        map.insert(split[0], fingerprints);
        overrides.insert(fmt, map);
    }
    resolver.setOverrideKeys(overrides);

    auto recp = new SignalRecipient(&resolver);
    QObject::connect(&resolver, &KeyResolver::keysResolved, recp, &SignalRecipient::keysResolved);

    QTimer::singleShot(1s, [&parser, &resolver]() {
        resolver.start(parser.isSet(QStringLiteral("approval")));
    });

    app.exec();
    return 0;
}

#include "test_keyresolver.moc"
