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

#include "identitymanager.h"
#include "editor_debug.h"
#include <KConfig>
#include <KConfigGroup>
#include <QRegularExpression>

IdentityManager::IdentityManager()
    : QObject(nullptr)
{
    mConfig = new KConfig(QStringLiteral("emailidentities_gpgol"));
    if (!mConfig->isConfigWritable(true)) {
        qCWarning(EDITOR_LOG) << "impossible to write on this file";
    }
    readConfig(mConfig);
}

IdentityManager::~IdentityManager()
{
    writeConfig();
}

IdentityManager &IdentityManager::self()
{
    static IdentityManager _self;
    return _self;
}

void IdentityManager::updateIdentity(KIdentityManagementCore::Identity identity)
{
    int i = 0;
    for (const auto &it : std::as_const(mIdentities)) {
        if (it.uoid() == identity.uoid()) {
            mIdentities[i] = identity;
            return;
        }
        i++;
    }
    qCWarning(EDITOR_LOG) << "Identity not found";
    mIdentities << identity;
}

KIdentityManagementCore::Identity IdentityManager::fromEmail(const QString &from, bool &isNew)
{
    const auto it = std::find_if(std::cbegin(mIdentities), std::cend(mIdentities), [&from, &isNew](const auto &identity) {
        isNew = false;
        return identity.primaryEmailAddress() == from;
    });

    if (it == std::cend(mIdentities)) {
        KIdentityManagementCore::Identity identity;
        identity.setPrimaryEmailAddress(from);
        identity.setWarnNotEncrypt(true);
        mIdentities.append(identity);
        isNew = true;
        return identity;
    }

    return *it;
}

KIdentityManagementCore::Identity IdentityManager::fromUoid(uint uoid)
{
    const auto it = std::find_if(std::cbegin(mIdentities), std::cend(mIdentities), [&uoid](const auto &identity) {
        return identity.uoid() == uoid;
    });

    if (it == std::cend(mIdentities)) {
        qFatal() << "Should not happen";
    }

    return *it;
}

QStringList IdentityManager::identityEmails() const
{
    QStringList emails;
    std::transform(std::cbegin(mIdentities), std::cend(mIdentities), std::back_inserter(emails), [](const auto &identity) {
        return identity.primaryEmailAddress();
    });

    return emails;
}

KIdentityManagementCore::Identity::List IdentityManager::identities() const
{
    return mIdentities;
}

void IdentityManager::writeConfig() const
{
    const QStringList identities = groupList(mConfig);
    QStringList::const_iterator groupEnd = identities.constEnd();
    for (QStringList::const_iterator group = identities.constBegin(); group != groupEnd; ++group) {
        mConfig->deleteGroup(*group);
    }
    int i = 0;
    for (const auto &identity : mIdentities) {
        KConfigGroup cg(mConfig, QStringLiteral("Identity #%1").arg(i));
        identity.writeConfig(cg);
    }
    mConfig->sync();
}

void IdentityManager::readConfig(KConfig *config)
{
    mIdentities.clear();

    const QStringList identities = groupList(config);
    if (identities.isEmpty()) {
        return; // nothing to be done...
    }

    QStringList::const_iterator groupEnd = identities.constEnd();
    for (QStringList::const_iterator group = identities.constBegin(); group != groupEnd; ++group) {
        KConfigGroup configGroup(config, *group);
        KIdentityManagementCore::Identity identity;
        identity.readConfig(configGroup);
        // Don't load invalid identity
        if (!identity.isNull() && !identity.primaryEmailAddress().isEmpty()) {
            mIdentities << identity;
        }
    }
    std::sort(mIdentities.begin(), mIdentities.end());
}

QStringList IdentityManager::groupList(KConfig *config) const
{
    static QRegularExpression identityRegex(QStringLiteral("^Identity #\\d+$"));
    return config->groupList().filter(identityRegex);
}
