#include "MainWidget.h"

// Qt
#include <QApplication>
#include <QDebug>
#include <QHeaderView>
#include <QLabel>
#include <QMenu>
#include <QMessageBox>
#include <QPushButton>
#include <QSettings>
#include <QStatusBar>
#include <QTableView>
#include <QTimer>
#include <QToolBar>
#include <QVBoxLayout>

// Self
#include "../def.h"
#include "LicenseModel/LicenseModel.h"
#include "EditClientDialog/EditClientDialog.h"

#define WINDOW_SIZE "WindowSize"

MainWidget::MainWidget(QWidget *parent)
    : QMainWindow(parent)
    , m_licenseModel(new LicenseModel(this))
{
    setWindowIcon(QIcon(QStringLiteral("qrc:/deps/icon.png")));
    setWindowTitle("LicenseManager");
    setMinimumSize({800, 600});
    resize(minimumSize());

    // Status bar
    {
        m_statusBar = new QStatusBar(this);
        setStatusBar(m_statusBar);
        m_statusLabel = new QLabel("No status", this);
        m_statusBar->addWidget(m_statusLabel);
        connect(m_licenseModel, &LicenseModel::statusChanged, this, &MainWidget::modelStatusChanged);
    }

    // Model init
    {
        if (m_licenseModel->getStatus() == LicenseModel::Status::DbStructError)
        {
            if (!m_licenseModel->prepareDatabase())
            {
                QTimer::singleShot(0, [&]() {
                    QMessageBox messageBox;
                    messageBox.setIcon(QMessageBox::Critical);
                    messageBox.setWindowTitle(tr("Error"));
                    messageBox.setText(tr("Error with prepare database"));
                    messageBox.setDetailedText(m_licenseModel->getStatusText());
                    messageBox.exec();
                    QApplication::quit();
                });
            }
        }
    }

    // Ui
    {
        m_tableView = new QTableView(this);
        m_tableView->horizontalHeader()->setStretchLastSection(true);
        m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
        m_tableView->setModel(m_licenseModel);
        setCentralWidget(m_tableView);

        connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWidget::selectionChanged);

        // ToolTip
        {
            m_toolBar = addToolBar("ToolBar");
            m_toolBar->setMovable(false);
            m_addClientToolBarAction = m_toolBar->addAction(QIcon(QStringLiteral(":/deps/add.png")), tr("Add client"));
            m_infoToolBarAction = m_toolBar->addAction(QIcon(QStringLiteral(":/deps/info.png")), tr("Get info"));

            connect(m_addClientToolBarAction, &QAction::triggered, this, &MainWidget::onAddClientTriggered);
            connect(m_infoToolBarAction, &QAction::triggered, this, &MainWidget::onGetInfoTriggered);
        }

        // Table Menu
        {
            m_menu = new QMenu(m_tableView);

            m_reloadTableMenuAction = m_menu->addAction(QIcon(QStringLiteral(":/deps/reload.png")), tr("Reload table"));
            m_menu->addSeparator();
            m_addClientsMenuAction = m_menu->addAction(QIcon(QStringLiteral(":/deps/add.png")), tr("Add client"));
            m_editClientsMenuAction = m_menu->addAction(QIcon(QStringLiteral(":/deps/edit.png")), tr("Edit client"));
            m_deleteClientsMenuAction = m_menu->addAction(QIcon(QStringLiteral(":/deps/delete.png")), tr("Delete client"));

            connect(m_reloadTableMenuAction, &QAction::triggered, this, &MainWidget::onReloadTableTriggered);
            connect(m_addClientsMenuAction, &QAction::triggered, this, &MainWidget::onAddClientTriggered);
            connect(m_editClientsMenuAction, &QAction::triggered, this, &MainWidget::onEditClientTriggered);
            connect(m_deleteClientsMenuAction, &QAction::triggered, this, &MainWidget::onDeleteClientTriggered);

            m_tableView->setContextMenuPolicy(Qt::CustomContextMenu);
            connect(m_tableView, &QTableView::customContextMenuRequested,
                    this, &MainWidget::onCustomContextMenuRequested);
        }
    }

    // Edit client dialog
    {
        m_editClientDialog = new EditClientDialog(m_licenseModel, this);
        connect(m_editClientDialog, &QDialog::finished, this, &MainWidget::onEditClientDialogClosed);
    }

    m_tableView->resizeColumnsToContents();
    selectionChanged({}, {});
    modelStatusChanged();
    loadSettings();
}

MainWidget::~MainWidget()
{
    saveSettings();
}

void MainWidget::onCustomContextMenuRequested(const QPoint &pos)
{
    m_menu->popup(m_tableView->viewport()->mapToGlobal(pos));
}

void MainWidget::onGetInfoTriggered()
{
    QDialog dialog(this);
    dialog.setModal(true);
    auto vLayout = new QVBoxLayout;
    dialog.setLayout(vLayout);
    QIcon icon(":/deps/icon.png");
    QLabel *iconLabel = new QLabel(&dialog);
    iconLabel->setPixmap(icon.pixmap(300, 300));
    iconLabel->setAlignment(Qt::AlignCenter);
    vLayout->addWidget(iconLabel);
    auto projectLabel = new QLabel(QString(tr("Project name: %1")).arg(PROJECT_VERSION_STR), &dialog);
    projectLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
    vLayout->addWidget(projectLabel);
    auto gitBranchLabel = new QLabel(QString("Git branch: %1").arg(GIT_BRANCH_STR), &dialog);
    gitBranchLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
    vLayout->addWidget(gitBranchLabel);
    auto gitCommitLabel = new QLabel(QString("Git commit: %1").arg(GIT_COMMIT_HASH_STR), &dialog);
    gitCommitLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
    vLayout->addWidget(gitCommitLabel);
    vLayout->addStretch();
    auto hLayout = new QHBoxLayout;
    hLayout->addStretch();
    auto closeButton = new QPushButton(tr("Close"), &dialog);
    hLayout->addWidget(closeButton);
    vLayout->addItem(hLayout);
    connect(closeButton, &QPushButton::clicked, &dialog, &QDialog::reject);
    dialog.exec();
}

void MainWidget::onReloadTableTriggered()
{
    m_licenseModel->updateModel();
}

void MainWidget::onAddClientTriggered()
{
    m_editClientDialog->setType(EditClientDialog::Type::Add);
    m_editClientDialog->clear();
    m_editClientDialog->show();
}

void MainWidget::onEditClientTriggered()
{
    m_editClientDialog->setType(EditClientDialog::Type::Edit);
    if (m_tableView->selectionModel()->selectedRows().size() != 1)
        return;
    m_editClientDialog->setClientInfo(m_tableView->selectionModel()->selectedRows().first().row());
    m_editClientDialog->show();
}

void MainWidget::onDeleteClientTriggered()
{
    auto selectedRows = m_tableView->selectionModel()->selectedRows();
    if (selectedRows.isEmpty())
        return;

    QList<int> list;
    for (auto i = selectedRows.size() - 1; i >= 0; --i)
        list << selectedRows.at(i).row();

    m_licenseModel->deleteClient(list);
}

void MainWidget::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
    Q_UNUSED(deselected);

    auto selectedCount = selected.size();
    m_editClientsMenuAction->setEnabled(selectedCount == 1);
    m_deleteClientsMenuAction->setEnabled(selectedCount > 0);
}

void MainWidget::closeEvent(QCloseEvent *event)
{
    QMessageBox::StandardButton reply;
    reply = QMessageBox::question(
        this,
        tr("Confirmation of exit"),
        tr("Are you sure you want to exit the app?"),
        QMessageBox::Yes | QMessageBox::No
    );

    if (reply == QMessageBox::Yes)
        event->accept();
    else
        event->ignore();
}

void MainWidget::loadSettings()
{
    QSettings settings(ORGANIZATION_NAME, metaObject()->className());
    if (settings.contains(WINDOW_SIZE))
        resize(settings.value(WINDOW_SIZE).toSize());
}

void MainWidget::saveSettings()
{
    QSettings settings(ORGANIZATION_NAME, metaObject()->className());
    settings.setValue(WINDOW_SIZE, size());
}

void MainWidget::onEditClientDialogClosed(int result)
{
    if (result == QDialog::Rejected)
        return;

    switch (m_editClientDialog->getType())
    {
    case EditClientDialog::Type::Edit:
        if (m_tableView->selectionModel()->selectedRows().size() != 1)
            return;
        m_licenseModel->editClient(m_editClientDialog->getLicenseItem(), m_tableView->selectionModel()->selectedRows().at(0).row());
        break;
    case EditClientDialog::Type::Add:
        m_licenseModel->addClient(m_editClientDialog->getLicenseItem());
        break;
    case EditClientDialog::Type::None:
        break;
    }
}

void MainWidget::modelStatusChanged()
{
    switch (m_licenseModel->getStatus())
    {
    case LicenseModel::Status::Ok:
        m_statusLabel->setText(tr("Database ready"));
        break;
    case LicenseModel::Status::DbExistError:
        m_statusLabel->setText(tr("Database exist error"));
        break;
    case LicenseModel::Status::DbStructError:
        m_statusLabel->setText(tr("Database struct error"));
        break;
    case LicenseModel::Status::Working:
        m_statusLabel->setText(tr("Working"));
        break;
    default:
        m_statusLabel->setText(tr("Unknown status"));
        break;
    }

    m_addClientToolBarAction->setEnabled(m_licenseModel->getStatus() == LicenseModel::Status::Ok);
    m_addClientsMenuAction->setEnabled(m_licenseModel->getStatus() == LicenseModel::Status::Ok);
    m_editClientsMenuAction->setEnabled(m_licenseModel->getStatus() == LicenseModel::Status::Ok);
    m_deleteClientsMenuAction->setEnabled(m_licenseModel->getStatus() == LicenseModel::Status::Ok);
}

