/*
 * 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/gitea/aqua/smolbote
 *
 * SPDX-License-Identifier: GPL-3.0
 */

#include "mainwindow.h"
#include "addressbar.h"
#include "bookmarks/bookmarkstoolbar.h"
#include "bookmarks/bookmarkswidget.h"
#include "browser.h"
#include "configuration.h"
#include "menubar.h"
#include "webengine/webprofile.h"
#include "webengine/webprofilemanager.h"
#include "webengine/webview.h"
#include "widgets/dockwidget.h"
#include "widgets/navigationbar.h"
#include "widgets/searchform.h"
#include <QApplication>
#include <QCloseEvent>
#include <QMessageBox>
#include <QStatusBar>

MainWindow::MainWindow(const Session::MainWindow &mainwindow_data, QMenu *appMenu, QWidget *parent)
    : QMainWindow(parent)
{
    Configuration config;

    // create UI
    defaultWindowTitle = config.value<QString>("mainwindow.title").value();
    setWindowTitle(defaultWindowTitle);
    resize(config.value<int>("mainwindow.width").value(), config.value<int>("mainwindow.height").value());
    if(config.value<bool>("mainwindow.maximized").value_or(false)) {
        setWindowState(Qt::WindowMaximized);
    }
    show();

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

    addressBar = new AddressBar(this);
    navigationToolBar->addWidget(addressBar);

    auto *app = qobject_cast<Browser *>(qApp);
    this->addToolBarBreak();
    this->addToolBar(new BookmarksToolbar(app->bookmarks()->model(), this));

    m_menuBar = new MenuBar(appMenu, this);
    setMenuBar(m_menuBar);

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

    // search box
    auto *searchAction = new QAction(this);
    config.shortcut<QAction>(*searchAction, "shortcuts.window.search");
    connect(searchAction, &QAction::triggered, this, [this]() {
        searchBox->setVisible(!searchBox->isVisible());
    });
    QMainWindow::addAction(searchAction);

    for(const auto &s : mainwindow_data.subwindows) {
        createSubWindow(s);
    }
    if(m_subwindows.isEmpty()) {
        const Session::SubWindow s;
        createSubWindow(s);
    }
}

void MainWindow::addDockWidget(Qt::DockWidgetArea area, QWidget *widget)
{
    QDockWidget *lastDock = nullptr;
    const auto docks = findChildren<QDockWidget *>();
    for(QDockWidget *dock : docks) {
        if(dockWidgetArea(dock) == area) {
            lastDock = dock;
        }
    }

    auto *dock = new DockWidget(widget->windowTitle(), this);
    dock->setMinimumWidth(460);
    dock->setWidget(widget);

    if(lastDock == nullptr) {
        QMainWindow::addDockWidget(area, dock);
    } else {
        tabifyDockWidget(lastDock, dock);
    }
}

void MainWindow::removeDockWidget(QWidget *widget)
{
    const auto docks = this->findChildren<QDockWidget *>();
    for(QDockWidget *dock : docks) {
        if(dock->widget() == widget) {
            dock->widget()->setParent(nullptr);
            dock->close();
        }
    }
}

void MainWindow::createTab(const QUrl &url)
{
    auto *w = qobject_cast<SubWindow *>(centralWidget());
    if(w != nullptr) {
        w->addTab(url);
    }
}

void MainWindow::createTab(const Session::WebView &tab_data)
{
    auto *w = qobject_cast<SubWindow *>(centralWidget());
    if(w != nullptr) {
        w->addTab(tab_data);
    }
}

SubWindow *MainWindow::createSubWindow(const Session::SubWindow &subwindow_data)
{
    WebProfileManager profileManager;

    auto *profile = profileManager.profile(subwindow_data.profile);
    if(profile == nullptr) {
        profile = WebProfile::defaultProfile();
    }
    auto *w = new SubWindow(this);
    w->setProfile(profile);
    m_subwindows.append(w);
    setCurrentSubWindow(w);
    m_menuBar->insertSubWindow(w);

    connect(w, &SubWindow::windowTitleChanged, this, [this, w](const QString &title) {
        if(w == currentSubWindow()) {
            setWindowTitle(QString("[%1] - %2").arg(title, defaultWindowTitle));
        }
    });

    connect(w, &SubWindow::aboutToClose, this, [this, w]() {
        m_subwindows.removeAll(w);
        if(m_subwindows.isEmpty()) {
            close();
        } else {
            setCurrentSubWindow(m_subwindows.last());
            w->deleteLater();
        }
    });

    if(subwindow_data.tabs.count() == 0) {
        w->addTab(profile->newtab());
        return w;
    }
    for(const auto &tab : subwindow_data.tabs) {
        w->addTab(tab);
    }
    return w;
}

void MainWindow::setCurrentSubWindow(SubWindow *subwindow)
{
    auto *previous = centralWidget();
    if(previous != nullptr) {
        previous->setParent(nullptr);
        previous->hide();
    }
    setCentralWidget(subwindow);
    subwindow->show();
    subwindow->setFocus();
    setWindowTitle(QString("[%1] - %2").arg(subwindow->windowTitle(), defaultWindowTitle));

    // connect signlas
    disconnect(viewChangedConnection);
    disconnect(statusBarConnection);

    setView(subwindow->currentView());
    viewChangedConnection = connect(subwindow, &SubWindow::currentViewChanged, this, &MainWindow::setView);
    statusBarConnection = connect(subwindow, &SubWindow::showStatusMessage, statusBar(), &QStatusBar::showMessage);
}

void MainWindow::setView(WebView *view)
{
    addressBar->connectView(view);
    navigationToolBar->connectWebView(view);
    searchBox->setView(view);
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if(m_subwindows.count() > 1) {
        const 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;
        }
    }
    event->accept();
}