/*
    SPDX-FileCopyrightText: 2014-2023 Anne Jan Brouwer <brouwer@annejan.com>
    SPDX-FileCopyrightText: 2018 Lukas Vogel <lukedirtwalker@gmail.com>
    SPDX-FileCopyrightText: 2018 Claudio Maradonna <penguyman@stronzi.org>
    SPDX-FileCopyrightText: 2023 g10 Code GmbH
    SPDX-FileContributor: Sune Stolborg Vuorela <sune@vuorela.dk>

    SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "passwordeditorwidget.h"
#include "config.h"
#include "passentry.h"
#include "passwordgeneratorwidget.h"
#include "ui_passwordeditorwidget.h"

#include <QFileInfo>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <qalgorithms.h>

PasswordEditorWidget::PasswordEditorWidget(ClipboardHelper *clipboardHelper, QWidget *parent)
    : QWidget(parent)
    , ui(std::make_unique<Ui::PasswordEditorWidget>())
    , m_clipboardHelper(clipboardHelper)
{
    ui->setupUi(this);

    connect(ui->createPasswordButton, &QAbstractButton::clicked, this, &PasswordEditorWidget::createPassword);
    connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &PasswordEditorWidget::accept);
    connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &PasswordEditorWidget::editorClosed);
}

void PasswordEditorWidget::setPassEntry(const PassEntry &passEntry)
{
    m_passEntry = passEntry;
    load();
}

PassEntry PasswordEditorWidget::passEntry() const
{
    return m_passEntry;
}

/**
 * @brief Pass{}{}wordDialog::~PasswordEditorWidget basic destructor.
 */
PasswordEditorWidget::~PasswordEditorWidget() = default;

/**
 * @brief PasswordEditorWidget::on_createPasswordButton_clicked generate a random
 * passwords.
 * @todo refactor when process is untangled from MainWindow class.
 */
void PasswordEditorWidget::createPassword()
{
    auto generator = PasswordGeneratorWidget::popupGenerator(m_clipboardHelper, this);
    connect(generator, &PasswordGeneratorWidget::appliedPassword, this, [this](const QString &newPassword) {
        ui->lineEditPassword->setPassword(newPassword);
    });
}

void PasswordEditorWidget::accept()
{
    Q_EMIT save(toRawContent());
    Q_EMIT editorClosed();
}

/**
 * @brief PasswordEditorWidget::setPassword populate the (templated) fields.
 * @param password
 */
void PasswordEditorWidget::load()
{
    // clear
    while (ui->formLayout->rowCount() > 1) {
        ui->formLayout->removeRow(1);
    }
    m_templateLines.clear();
    m_otherLines.clear();

    m_fields = Config::self()->passTemplate();

    // Setup password
    ui->title->setText(m_passEntry.name());
    ui->lineEditPassword->setPassword(m_passEntry.password());

    // Setup defined templated values
    QWidget *previous = ui->createPasswordButton;
    if (Config::self()->templateEnabled()) {
        auto namedValues = m_passEntry.namedValues();
        const auto fields = Config::self()->passTemplate();
        for (const QString &field : std::as_const(fields)) {
            if (field.isEmpty()) {
                continue;
            }

            auto line = new QLineEdit();
            line->setObjectName(field);
            line->setText(namedValues.takeValue(field));
            ui->formLayout->addRow(new QLabel(i18nc("Field name", "%1:", field)), line);
            setTabOrder(previous, line);
            m_templateLines.append(line);
            previous = line;
        }

        // setup remaining values (if there are)
        for (const auto &namedValue : std::as_const(namedValues)) {
            auto line = new QLineEdit();
            line->setObjectName(namedValue.name);
            line->setText(namedValue.value);
            ui->formLayout->addRow(new QLabel(namedValue.name), line);
            setTabOrder(previous, line);
            m_otherLines.append(line);
            previous = line;
        }
    }

    // setup notes
    ui->plainTextEdit->insertPlainText(m_passEntry.remainingData());
}

QString PasswordEditorWidget::toRawContent() const
{
    QString passFile = ui->lineEditPassword->password() + QLatin1Char('\n');
    QList<QLineEdit *> allLines(m_templateLines);
    allLines.append(m_otherLines);
    for (QLineEdit *line : allLines) {
        const QString text = line->text();
        if (text.isEmpty()) {
            continue;
        }
        passFile += line->objectName() + QStringLiteral(": ") + text + QLatin1Char('\n');
    }
    passFile += ui->plainTextEdit->toPlainText();

    if (passFile.right(1) != QLatin1Char('\n')) {
        passFile += QLatin1Char('\n');
    }
    return passFile;
}
