/*
 * This file is part of smolbote. It's copyrighted by the contributors recorded
 * in the version control history of the file, available from its original
 * location: https://neueland.iserlohn-fortress.net/smolbote.hg
 *
 * SPDX-License-Identifier: GPL-3.0
 */

#include "mainwindow.h"
#include "addressbar/addressbar.h"
#include "webengine/webview.h"
#include "widgets/navigationbar.h"
#include "widgets/searchform.h"
#include "window.h"
#include <QApplication>
#include <QCloseEvent>
#include <QDockWidget>
#include <QLineEdit>
#include <QMdiArea>
#include <QMdiSubWindow>
#include <QMenuBar>
#include <QMessageBox>
#include <QShortcut>
#include <QStatusBar>
#include <QToolBar>
#include <QUrl>
#include <about/aboutdialog.h>
#include <configuration/configuration.h>

MainWindow::MainWindow(std::shared_ptr<Configuration> &config, QWidget *parent)
    : QMainWindow(parent)
    , mdiArea(new QMdiArea(this))
{
    Q_ASSERT(config);
    m_config = config;

    // create UI
    resize(config->value<int>("mainwindow.width").value(), config->value<int>("mainwindow.height").value());
    setWindowTitle(QString::fromStdString(config->value<std::string>("mainwindow.title").value()));
    if(config->value<bool>("mainwindow.maximized").value())
        showMaximized();
    else
        show();

    createMenuBar();

    auto *navigationToolBar = new NavigationBar(config->section("navigation"), this);
    navigationToolBar->setMovable(config->value<bool>("navigation.movable").value());
    addToolBar(Qt::TopToolBarArea, navigationToolBar);
    navigationToolBar->connectWebView(nullptr);

    addressBar = new AddressBar(config->section("addressbar"), this);
    navigationToolBar->addWidget(addressBar);

    setCentralWidget(mdiArea);
    mdiArea->setFocus();

    // status bar
    searchBox = new SearchForm(this);
    statusBar()->addPermanentWidget(searchBox);
    searchBox->setVisible(false);

    // connect signlas
    connect(mdiArea, &QMdiArea::subWindowActivated, this, [this, navigationToolBar](QMdiSubWindow *window) {
        disconnect(addressBarConnection);
        disconnect(navigationBarConnection);
        disconnect(searchBoxConnection);
        disconnect(statusBarConnection);
        windowMenu->setMenu(nullptr);

        auto *w = qobject_cast<Window *>(window);
        if(w == nullptr) {
            // no current subwindow, clear everything
            setWindowTitle(tr("smolbote"));
            addressBar->connectWebView(nullptr);
            navigationToolBar->connectWebView(nullptr);
            searchBox->setView(nullptr);
        } else {
            windowMenu->setMenu(w->systemMenu());
            addressBar->connectWebView(w->currentView());
            addressBarConnection = connect(w, &Window::currentViewChanged, addressBar, &AddressBar::connectWebView);
            navigationToolBar->connectWebView(w->currentView());
            navigationBarConnection = connect(w, &Window::currentViewChanged, navigationToolBar, &NavigationBar::connectWebView);
            searchBox->setView(w->currentView());
            searchBoxConnection = connect(w, &Window::currentViewChanged, searchBox, &SearchForm::setView);
            statusBarConnection = connect(w, &Window::showStatusMessage, statusBar(), &QStatusBar::showMessage);
        }
    });

    auto *tileShortcut = new QShortcut(QKeySequence(config->value<std::string>("mainwindow.shortcuts.tileWindows").value().c_str()), this);
    connect(tileShortcut, &QShortcut::activated, this, [=]() {
        mdiArea->tileSubWindows();
    });

    auto *searchShortcut = new QShortcut(QKeySequence(config->value<std::string>("mainwindow.shortcuts.search").value().c_str()), this);
    connect(searchShortcut, &QShortcut::activated, this, [=]() {
        searchBox->setVisible(!searchBox->isVisible());
    });
}

MainWindow::~MainWindow()
{
    disconnect(addressBarConnection);
    disconnect(navigationBarConnection);
    disconnect(searchBoxConnection);
    disconnect(statusBarConnection);
}

void MainWindow::createMenuBar()
{
    auto *smolboteMenu = menuBar()->addMenu(qApp->applicationDisplayName());
    smolboteMenu->addAction(tr("New tab group"), this, [this]() {
        createSubWindow(QUrl::fromUserInput("about:blank"));
    },
        QKeySequence(m_config->value<std::string>("mainwindow.shortcuts.newGroup").value().c_str()));
    smolboteMenu->addAction(tr("New window"))->setEnabled(false);

    smolboteMenu->addSeparator();

    smolboteMenu->addAction(tr("About"), this, [this]() {
        auto *dlg = new AboutDialog(this);
        dlg->exec();
    },
        QKeySequence(m_config->value<std::string>("mainwindow.shortcuts.about").value().c_str()));
    smolboteMenu->addAction(tr("About Qt"), qApp, &QApplication::aboutQt);

    smolboteMenu->addSeparator();

    smolboteMenu->addAction(tr("Quit"), qApp, &QApplication::quit,
        QKeySequence(m_config->value<std::string>("mainwindow.shortcuts.quit").value().c_str()));

    windowMenu = menuBar()->addAction(tr("Window"));
    toolsMenu = menuBar()->addMenu(tr("Tools"));
}

void MainWindow::addAction(ActionLocation where, QAction *action)
{
    switch(where) {
    case ToolsMenu:
        toolsMenu->addAction(action);
        break;
    default:
        QMainWindow::addAction(action);
        break;
    }
}

void MainWindow::addDockWidget(Qt::DockWidgetArea area, QWidget *widget)
{
    QDockWidget *dock = new QDockWidget(widget->windowTitle(), this);
    dock->setAttribute(Qt::WA_DeleteOnClose, true);
    dock->setWidget(widget);

    connect(dock, &QDockWidget::visibilityChanged, [dock](bool visible) {
        if(!visible && dock->widget()) {
            dock->widget()->setParent(nullptr);
        }
    });

    QMainWindow::addDockWidget(area, dock);
}

void MainWindow::createTab(const QUrl &url)
{
    auto *w = qobject_cast<Window *>(mdiArea->currentSubWindow());
    if(w == nullptr) {
        w = createSubWindow(url);
    } else {
        w->addTab(url);
    }
}

Window *MainWindow::createSubWindow(const QUrl &url)
{
    auto *w = new Window(m_config->section("window"), this);
    mdiArea->addSubWindow(w);
    w->showMaximized();
    w->setFocus();

    w->addTab(url);

    return w;
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if(mdiArea->subWindowList().count() > 1) {
        int choice = QMessageBox::question(this, tr("Close multiple subwindows?"), tr("Do you want to close all subwindows?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
        if(choice == QMessageBox::No) {
            event->ignore();
            return;
        }
    }

    mdiArea->closeAllSubWindows();
    if(mdiArea->currentSubWindow())
        event->ignore();
    else
        event->accept();
}