#include "versiondialog.h"

#include <utils/misc.h>

#include <QDebug>
#include <QJSValue>
#include <QJSValueIterator>
#include <QPushButton>
#include <QSplitter>

#include "mainwindow.h"
#include "services/settingsservice.h"
#include "ui_versiondialog.h"

VersionDialog::VersionDialog(const QJSValue &versions, QWidget *parent)
    : MasterDialog(parent), ui(new Ui::VersionDialog) {
    ui->setupUi(this);
    afterSetupUI();
    ui->tabWidget->setCurrentIndex(0);

    // Init the note text edit search-frame
    ui->noteTextEdit->initSearchFrame(ui->noteTextEditSearchFrame);

    setupMainSplitter();

    QPushButton *button;
    ui->buttonBox->clear();

    button = new QPushButton(tr("&Restore selected version"));
    button->setProperty("ActionRole", Restore);
    button->setDefault(false);
    button->setIcon(QIcon::fromTheme(QStringLiteral("edit-download"),
                                     QIcon(":/icons/breeze-qownnotes/16x16/edit-download.svg")));
    ui->buttonBox->addButton(button, QDialogButtonBox::ActionRole);

    button = new QPushButton(tr("&Cancel"));
    button->setProperty("ActionRole", Cancel);
    button->setIcon(QIcon::fromTheme(QStringLiteral("dialog-cancel"),
                                     QIcon(":/icons/breeze-qownnotes/16x16/dialog-cancel.svg")));
    button->setDefault(true);
    ui->buttonBox->addButton(button, QDialogButtonBox::ActionRole);

    connect(this->ui->buttonBox, SIGNAL(clicked(QAbstractButton *)),
            SLOT(dialogButtonClicked(QAbstractButton *)));
    connect(this, SIGNAL(finished(int)), this, SLOT(storeSettings()));

    QString itemName;
    QString diffHtml;
    ui->versionListWidget->clear();
    _diffList = new QStringList();
    _dataList = new QStringList();
    const auto currentNote = MainWindow::instance()->getCurrentNote();
    const bool canDecryptNoteText = currentNote.canDecryptNoteText();

    // If the text was decrypted, we use the styling of the encrypted note text edit
    if (canDecryptNoteText) {
        static const QString encryptedStyle =
            "QTextEdit,QPlainTextEdit {border: 3px dashed #aa0000;}";
        ui->noteTextEdit->setStyleSheet(encryptedStyle);
        ui->diffBrowser->setStyleSheet(encryptedStyle);
    }

    // Init the iterator for the versions
    QJSValueIterator versionsIterator(versions);

    // Iterate over the versions
    while (versionsIterator.hasNext()) {
        versionsIterator.next();
        QJSValue property =
            versionsIterator.value().property(QStringLiteral("humanReadableTimestamp"));

        if (property.isUndefined()) {
            continue;
        }

        itemName = property.toString();

        if (itemName.isEmpty()) {
            continue;
        }

        diffHtml = "<style>" + Utils::Misc::genericCSS() + "</style>" +
                   versionsIterator.value().property(QStringLiteral("diffHtml")).toString();
        diffHtml.replace(QLatin1String("\\n"), QLatin1String("&para;<br />"));
        diffHtml.replace(QLatin1String("\n"), QLatin1String("<br />"));

        ui->versionListWidget->addItem(itemName);
        _diffList->append(diffHtml);
        QString noteText = versionsIterator.value().property(QStringLiteral("data")).toString();

        // Decrypt the note text if possible
        if (canDecryptNoteText) {
            noteText = currentNote.getDecryptedNoteText(Note::parseEncryptedNoteText(noteText));
        }

        _dataList->append(noteText);
    }

    if (!_diffList->isEmpty()) {
        ui->versionListWidget->setCurrentRow(0);
        ui->diffBrowser->setHtml(_diffList->at(0));
    }
}

void VersionDialog::setupMainSplitter() {
    versionSplitter = new QSplitter;

    versionSplitter->addWidget(ui->versionListWidget);
    versionSplitter->addWidget(ui->tabWidget);

    // restore splitter sizes
    SettingsService settings;
    QByteArray state = settings.value(QStringLiteral("versionSplitterSizes")).toByteArray();
    versionSplitter->restoreState(state);

    ui->gridLayout->addWidget(versionSplitter);
}

void VersionDialog::storeSettings() {
    // store the splitter sizes
    SettingsService settings;
    settings.setValue(QStringLiteral("versionSplitterSizes"), versionSplitter->saveState());
}

VersionDialog::~VersionDialog() { delete ui; }

void VersionDialog::on_versionListWidget_currentRowChanged(int currentRow) {
    ui->diffBrowser->setHtml(_diffList->value(currentRow));
    ui->noteTextEdit->setPlainText(_dataList->value(currentRow));
}

void VersionDialog::dialogButtonClicked(QAbstractButton *button) {
    int actionRole = button->property("ActionRole").toInt();

    if (actionRole == Restore) {
        MainWindow::instance()->setCurrentNoteText(
            _dataList->value(ui->versionListWidget->currentRow()));
    }

    this->close();
}
