#include "backgroundpropertiesdialog.h"
#include "ui_backgroundpropertiesdialog.h"

#include <QFileDialog>
#include <QDebug>
#include <QMessageBox>

#include "projectcontainer.h"
#include "models/projecttreemodel.h"
#include "imageeditordialog.h"
#include "mainwindow.h"
#include "imagehelpers.h"
#include "editorguiutils.h"

BackgroundPropertiesDialog::BackgroundPropertiesDialog(Background &background, ProjectTreeModel &projectModel, MainWindow &mainWindow) :
    QDialog{&mainWindow},
    m_ui{std::make_unique<Ui::BackgroundPropertiesDialog>()},
    m_background{background},
    m_projectModel{projectModel},
    m_mainWindow{mainWindow},
    m_pixmap{m_background.pixmap}
{
    m_ui->setupUi(this);

    updateTitle();

    improveButtonBox(m_ui->buttonBox);

    m_ui->lineEditName->setText(m_background.name);
    updateSpriteInfo();
    m_ui->checkBoxTileset->setChecked(m_background.tileset);

    connect(&m_projectModel, &ProjectTreeModel::backgroundNameChanged,
            this, &BackgroundPropertiesDialog::backgroundNameChanged);

    connect(m_ui->pushButtonLoad, &QAbstractButton::clicked,
            this, &BackgroundPropertiesDialog::loadBackground);
    connect(m_ui->pushButtonSave, &QAbstractButton::clicked,
            this, &BackgroundPropertiesDialog::saveBackground);
    connect(m_ui->pushButtonEdit, &QAbstractButton::clicked,
            this, &BackgroundPropertiesDialog::editBackground);

    connect(m_ui->lineEditName, &QLineEdit::textChanged,
            this, &BackgroundPropertiesDialog::changed);
    connect(m_ui->checkBoxTileset, &QCheckBox::checkStateChanged,
            this, &BackgroundPropertiesDialog::changed);
}

BackgroundPropertiesDialog::~BackgroundPropertiesDialog() = default;

void BackgroundPropertiesDialog::accept()
{
    if (!m_unsavedChanges)
    {
        QDialog::reject();
        return;
    }

    if (m_background.name != m_ui->lineEditName->text())
    {
        if (!m_projectModel.rename<Background>(m_background, m_ui->lineEditName->text()))
        {
            QMessageBox::critical(this, tr("Renaming Background failed!"), tr("Renaming Background failed!"));
            return;
        }
    }

    if (!m_projectModel.setBackgroundPixmap(m_background, std::move(m_pixmap)))
    {
        QMessageBox::critical(this, tr("Setting Background pixmap failed!"), tr("Setting Background pixmap failed!"));
        return;
    }

    m_background.tileset = m_ui->checkBoxTileset->isChecked();

    QDialog::accept();
}

void BackgroundPropertiesDialog::reject()
{
    if (!m_unsavedChanges)
    {
        QDialog::reject();
        return;
    }

    const auto result = QMessageBox::warning(
        this,
        tr("The Background has been modified."),
        tr("Do you want to save your changes?"),
        QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
        QMessageBox::Save
    );
    switch (result)
    {
    case QMessageBox::Save:
        accept();
        return;
    case QMessageBox::Discard:
        QDialog::reject();
        return;
    case QMessageBox::Cancel:
        return;
    default:
        qWarning() << "unexpected dialog result" << result;
    }
}

void BackgroundPropertiesDialog::loadBackground()
{
    auto pixmap = loadPixmap(this);
    if (pixmap.isNull())
        return;

    m_pixmap = std::move(pixmap);
    changed();
    updateSpriteInfo();
}

void BackgroundPropertiesDialog::saveBackground()
{
    if (m_pixmap.isNull())
    {
        QMessageBox::warning(this, tr("No background available to save!"), tr("No background available to save!"));
        return;
    }

    saveImage(this, m_pixmap.toImage());
}

void BackgroundPropertiesDialog::editBackground()
{
    ImageEditorDialog dialog {
        m_pixmap,
        tr("Image Editor: %0").arg(m_background.name),
        m_mainWindow.settings(),
        this
    };
    if (dialog.exec() == QDialog::Accepted)
    {
        m_pixmap = dialog.pixmap();
        changed();
        updateSpriteInfo();
    }
}

void BackgroundPropertiesDialog::changed()
{
    if (!m_unsavedChanges)
    {
        m_unsavedChanges = true;
        updateTitle();
    }
}

void BackgroundPropertiesDialog::backgroundNameChanged(const Background &background)
{
    if (&background != &m_background)
        return;

    {
        QSignalBlocker blocker{m_ui->lineEditName};
        m_ui->lineEditName->setText(background.name);
    }

    updateTitle();
}

void BackgroundPropertiesDialog::updateTitle()
{
    setWindowTitle(tr("Background Properties: %0%1")
                       .arg(m_background.name)
                       .arg(m_unsavedChanges ? tr("*") : QString{})
                   );
}

void BackgroundPropertiesDialog::updateSpriteInfo()
{
    m_ui->labelWidth->setText(tr("Width: %0").arg(m_pixmap.width()));
    m_ui->labelHeight->setText(tr("Height: %0").arg(m_pixmap.height()));
    m_ui->labelPreview->setPixmap(m_pixmap);
}
