/*
    SPDX-FileCopyrightText: 2002-2004 Marc Mutz <mutz@kde.org>
    SPDX-FileCopyrightText: 2007 Tom Albers <tomalbers@kde.nl>
    SPDX-FileCopyrightText: 2009 Thomas McGuire <mcguire@kde.org>

    SPDX-License-Identifier: LGPL-2.0-or-later
*/

#include "signature.h"

#include "editor_debug.h"
#include <KConfigGroup>
#include <KLocalizedString>
#include <KProcess>

#include <QDir>
#include <QTextBlock>
#include <QTextDocument>

#include <cassert>

using namespace KIdentityManagementCore;

class KIdentityManagementCore::SignaturePrivate
{
public:
    explicit SignaturePrivate(Signature *qq)
        : q(qq)
    {
    }

    void assignFrom(const KIdentityManagementCore::Signature &that);

    QString text;
    Signature::Type type = Signature::Disabled;
    bool enabled = false;
    Signature *const q;
};

void SignaturePrivate::assignFrom(const KIdentityManagementCore::Signature &that)
{
    text = that.text();
    type = that.type();
    enabled = that.isEnabledSignature();
}

QDataStream &operator<<(QDataStream &stream, const KIdentityManagementCore::Signature::EmbeddedImagePtr &img)
{
    return stream << img->image << img->name;
}

QDataStream &operator>>(QDataStream &stream, const KIdentityManagementCore::Signature::EmbeddedImagePtr &img)
{
    return stream >> img->image >> img->name;
}

Signature::Signature()
    : d(new SignaturePrivate(this))
{
    d->type = Disabled;
}

Signature::Signature(const QString &text)
    : d(new SignaturePrivate(this))
{
    d->type = Inlined;
    d->text = text;
}

Signature::Signature(const Signature &that)
    : d(new SignaturePrivate(this))
{
    d->assignFrom(that);
}

Signature &Signature::operator=(const KIdentityManagementCore::Signature &that)
{
    if (this == &that) {
        return *this;
    }

    d->assignFrom(that);
    return *this;
}

Signature::~Signature() = default;

QString Signature::rawText(bool *ok, QString *errorMessage) const
{
    switch (d->type) {
    case Disabled:
        if (ok) {
            *ok = true;
        }
        return {};
    case Inlined:
        if (ok) {
            *ok = true;
        }
        return d->text;
    }
    qCritical() << "Signature::type() returned unknown value!";
    return {}; // make compiler happy
}

QString Signature::withSeparator(bool *ok, QString *errorMessage) const
{
    QString signature = rawText(ok, errorMessage);
    if (ok && (*ok) == false) {
        return {};
    }

    if (signature.isEmpty()) {
        return signature; // don't add a separator in this case
    }

    QString newline = QStringLiteral("\n");

    if (signature.startsWith(QLatin1StringView("-- ") + newline) || (signature.indexOf(newline + QLatin1StringView("-- ") + newline) != -1)) {
        // already have signature separator at start of sig or inside sig:
        return signature;
    } else {
        // need to prepend one:
        return QLatin1StringView("-- ") + newline + signature;
    }
}

// config keys and values:
static const char sigTypeKey[] = "Signature Type";
static const char sigTypeInlineValue[] = "inline";
static const char sigTypeDisabledValue[] = "disabled";
static const char sigTextKey[] = "Inline Signature";
static const char sigEnabled[] = "Signature Enabled";

void Signature::readConfig(const KConfigGroup &config)
{
    QString sigType = config.readEntry(sigTypeKey);
    if (sigType == QLatin1StringView(sigTypeInlineValue)) {
        d->type = Inlined;
    } else if (sigType == QLatin1StringView(sigTypeDisabledValue)) {
        d->enabled = false;
    }
    if (d->type != Disabled) {
        d->enabled = config.readEntry(sigEnabled, true);
    }

    d->text = config.readEntry(sigTextKey);
}

void Signature::writeConfig(KConfigGroup &config) const
{
    switch (d->type) {
    case Inlined:
        config.writeEntry(sigTypeKey, sigTypeInlineValue);
        break;
    default:
        break;
    }
    config.writeEntry(sigTextKey, d->text);
    config.writeEntry(sigEnabled, d->enabled);
}

// --------------------- Operators -------------------//

QDataStream &KIdentityManagementCore::operator<<(QDataStream &stream, const KIdentityManagementCore::Signature &sig)
{
    return stream << static_cast<quint8>(sig.type()) << sig.text() << sig.isEnabledSignature();
}

QDataStream &KIdentityManagementCore::operator>>(QDataStream &stream, KIdentityManagementCore::Signature &sig)
{
    quint8 s;
    QString path;
    QString text;
    QString saveLocation;
    QList<Signature::EmbeddedImagePtr> lst;
    bool enabled;
    stream >> s >> path >> text >> saveLocation >> lst >> enabled;
    sig.setText(text);
    sig.setEnabledSignature(enabled);
    sig.setType(static_cast<Signature::Type>(s));
    return stream;
}

bool Signature::operator==(const Signature &other) const
{
    if (d->type != other.type()) {
        return false;
    }

    if (d->enabled != other.isEnabledSignature()) {
        return false;
    }

    switch (d->type) {
    case Inlined:
        return d->text == other.text();
    default:
    case Disabled:
        return true;
    }
}

// --------------- Getters -----------------------//

QString Signature::text() const
{
    return d->text;
}

Signature::Type Signature::type() const
{
    return d->type;
}

// --------------- Setters -----------------------//

void Signature::setText(const QString &text)
{
    d->text = text;
    d->type = Inlined;
}

void Signature::setType(Type type)
{
    d->type = type;
}

void Signature::setEnabledSignature(bool enabled)
{
    d->enabled = enabled;
}

bool Signature::isEnabledSignature() const
{
    return d->enabled;
}
