//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/Tuning/ParameterBackupWidget.cpp
//! @brief     Implements class ParameterBackupWidget.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2023
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "GUI/View/Tuning/ParameterBackupWidget.h"
#include "Base/Util/Assert.h"
#include "GUI/Model/Par/ParameterTreeItems.h"
#include "GUI/View/Base/ActionFactory.h"
#include <QBoxLayout>
#include <QDateTime>
#include <QDialog>
#include <QLineEdit>

namespace {
void resizeLineEditToContents(QLineEdit* lineedit)
{
    QSize text_size = lineedit->fontMetrics().size(0, lineedit->text());
    lineedit->setMinimumSize(text_size + QSize(15, 0));
}

class NewSnapshotDialog : public QDialog {
public:
    explicit NewSnapshotDialog(QString& newName, QWidget* parent = nullptr)
        : QDialog(parent)
    {
        setWindowTitle("New snapshot");
        setMinimumWidth(240);

        auto* mainLayout = new QVBoxLayout(this);

        QString dateTime = QDateTime::currentDateTime().toString("<dd.MM.yyyy | hh:mm:ss>");
        auto* lineEdit = new QLineEdit("State at " + dateTime);
        lineEdit->selectAll();
        mainLayout->addWidget(lineEdit);
        connect(lineEdit, &QLineEdit::textEdited, [this, lineEdit] {
            ::resizeLineEditToContents(lineEdit);
            adjustSize();
        });
        ::resizeLineEditToContents(lineEdit);

        auto* okButton = new QPushButton("OK");
        okButton->setFixedWidth(50);
        mainLayout->addWidget(okButton, 0, Qt::AlignCenter);
        okButton->setDefault(true);
        connect(okButton, &QPushButton::clicked, [this, &newName, lineEdit] {
            newName = lineEdit->text();
            accept();
        });
    }
};
} // namespace

ParameterBackupWidget::ParameterBackupWidget(QWidget* parent)
    : QWidget(parent)
    , m_combo(new QComboBox)
{
    auto* mainLayout = new QVBoxLayout(this);

    auto* h1 = new QHBoxLayout;
    h1->setAlignment(Qt::AlignLeft);

    m_combo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
    h1->addWidget(m_combo);

    m_remove = new QPushButton(QIcon(":/images/delete.svg"), "Remove");
    m_remove->setToolTip("Remove selected snapshot");
    h1->addWidget(m_remove);

    auto* h2 = new QHBoxLayout;
    h2->setAlignment(Qt::AlignLeft);
    m_create = new QPushButton(QIcon(":/images/shape-square-plus.svg"), "New snapshot");
    m_create->setToolTip("Add new snapshot of parameter tree");
    h2->addWidget(m_create);

    m_reset = new QPushButton(QIcon(":/images/undo.svg"), "Reset");
    m_reset->setToolTip("Reset parameter tree to selected snapshot");
    connect(m_reset, &QPushButton::clicked, [this] { backupSwitched(m_combo->currentIndex()); });
    h2->addWidget(m_reset);

    mainLayout->addLayout(h1);
    mainLayout->addLayout(h2);
}

void ParameterBackupWidget::setParameterContainer(ParameterContainerItem* container)
{
    ASSERT(container);
    m_container = container;

    // new snapshot
    disconnect(m_create, nullptr, nullptr, nullptr);
    connect(m_create, &QPushButton::clicked, [this] {
        QString newName;
        NewSnapshotDialog dialog(newName);
        if (dialog.exec() == QDialog::Accepted)
            m_container->addBackupValues(newName);
        fillCombo();
        QSignalBlocker b(m_combo);
        m_combo->setCurrentIndex(m_combo->count() - 1);
        m_remove->setEnabled(true);
    });

    // delete snapshot
    disconnect(m_remove, nullptr, nullptr, nullptr);
    connect(m_remove, &QPushButton::clicked, [this] {
        if (m_combo->currentIndex() >= 0) {
            m_container->deleteBackupValues(m_combo->currentIndex());
            fillCombo();
        }
    });

    // update combo
    fillCombo();
}

void ParameterBackupWidget::onComboChange(int index)
{
    m_remove->setDisabled(m_combo->currentIndex() <= 0);
    m_container->setCurrentIndex(index);
    emit backupSwitched(index);
}

void ParameterBackupWidget::fillCombo()
{
    disconnect(m_combo, nullptr, nullptr, nullptr);

    int index = m_container->currentIndex();
    m_combo->clear();
    m_combo->addItems(m_container->backupTitles());
    if (index >= 0) {
        if (index < m_combo->count())
            m_combo->setCurrentIndex(index);
        else
            m_combo->setCurrentIndex(m_combo->count() - 1);
    }
    m_remove->setDisabled(m_combo->currentIndex() <= 0);

    connect(m_combo, &QComboBox::currentIndexChanged, this, &ParameterBackupWidget::onComboChange);
}