/*
 * 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 "subwindow.h"
#include "browser.h"
#include "tabwidget.h"
#include "webengine/webview.h"
#include <QAction>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMenu>
#include <QShortcut>
#include <QStyle>
#include <QTabBar>
#include <QToolButton>
#include <configuration/configuration.h>
#include <web/profilemanager.h>
#include <web/webprofile.h>

SubWindow::SubWindow(const std::unique_ptr<Configuration> &config, QWidget *parent, Qt::WindowFlags flags)
    : QMdiSubWindow(parent, flags)
    , tabWidget(new TabWidget(this))
{
    // delete this window when it closes
    setAttribute(Qt::WA_DeleteOnClose, true);

    resize(800, 600);
    setWidget(tabWidget);

    m_profile = WebProfile::defaultProfile();

    // system menu
    {
        QMenu *menu = systemMenu();
        auto *firstAction = menu->actions().at(0);

        auto *profileName_action = new QAction(tr("Profile: %1").arg(m_profile->name()), menu);
        profileName_action->setEnabled(false);
        menu->insertAction(firstAction, profileName_action);

        auto *loadProfile_menu = new QMenu(tr("Load profile"), menu);
        menu->insertMenu(firstAction, loadProfile_menu);

        Browser *browser = qobject_cast<Browser *>(qApp);
        Q_CHECK_PTR(browser);

        auto *profileManager = dynamic_cast<Browser *>(qApp)->getProfileManager();
        loadProfile_menu->addActions(profileManager->createProfileMenu([this, profileName_action](WebProfile *profile) {
                                                       this->setProfile(profile);
                                                       profileName_action->setText(tr("Profile: %1").arg(profile->name()));
                                                   },
                                                       this)
                                         ->actions());

        menu->insertSeparator(firstAction);
    }

    // new tab button
    auto *newTab_button = new QToolButton(this);
    newTab_button->setIcon(style()->standardIcon(QStyle::SP_FileIcon));
    newTab_button->setToolTip(tr("Add tab"));
    newTab_button->setShortcut(QKeySequence(config->value<QString>("subwindow.shortcuts.new").value()));
    connect(newTab_button, &QToolButton::clicked, this, [=]() {
        auto index = addTab(WebProfile::defaultProfile()->newtab());
        tabWidget->setCurrentIndex(index);
    });
    newTab_button->setMenu(tabWidget->createTabMenu(newTab_button));
    tabWidget->setCornerWidget(newTab_button, Qt::TopRightCorner);

    // general actions
    auto *closeTab_shortcut = new QShortcut(QKeySequence(config->value<QString>("subwindow.shortcuts.close").value()), this);
    connect(closeTab_shortcut, &QShortcut::activated, this, [=]() {
        tabWidget->deleteTab(tabWidget->currentIndex());
    });

    auto *leftTab_shortcut = new QShortcut(QKeySequence(config->value<QString>("subwindow.shortcuts.left").value()), this);
    connect(leftTab_shortcut, &QShortcut::activated, this, [=]() {
        tabWidget->setCurrentIndex(qMax(0, tabWidget->currentIndex() - 1));
    });

    auto *moveTabLeft_shortcut = new QShortcut(QKeySequence(config->value<QString>("subwindow.shortcuts.moveLeft").value()), this);
    connect(moveTabLeft_shortcut, &QShortcut::activated, this, [=]() {
        auto idx = tabWidget->currentIndex();
        tabWidget->tabBar()->moveTab(idx, idx - 1);
    });

    auto *rightTab_shortcut = new QShortcut(QKeySequence(config->value<QString>("subwindow.shortcuts.right").value()), this);
    connect(rightTab_shortcut, &QShortcut::activated, this, [=]() {
        tabWidget->setCurrentIndex(qMin(tabWidget->currentIndex() + 1, tabWidget->count() - 1));
    });

    auto *moveTabRight_shortcut = new QShortcut(QKeySequence(config->value<QString>("subwindow.shortcuts.moveRight").value()), this);
    connect(moveTabRight_shortcut, &QShortcut::activated, this, [=]() {
        auto idx = tabWidget->currentIndex();
        tabWidget->tabBar()->moveTab(idx, idx + 1);
    });

    auto *fullScreen_shortcut = new QShortcut(QKeySequence(config->value<QString>("subwindow.shortcuts.fullscreen").value()), this);
    connect(fullScreen_shortcut, &QShortcut::activated, this, [=]() {
        auto *w = this->window();
        if(w->isFullScreen())
            w->showNormal();
        else
            w->showFullScreen();
    });

    connect(tabWidget, &TabWidget::currentChanged, [this](int index) {
        if(index < 0) {
            // last tab has been closed
            close();
        } else {
            auto *view = dynamic_cast<WebView *>(tabWidget->widget(index));
            Q_CHECK_PTR(view);

            disconnect(titleConnection);
            disconnect(linkHoveredConnection);

            titleConnection = connect(view, &WebView::titleChanged, this, [this](const QString &title) {
                auto *v = qobject_cast<WebView *>(sender());
                this->setWindowTitle(QString("%1 :%2").arg(title, v->profile()->name()));
            });
            setWindowTitle(QString("%1 :%2").arg(view->title(), view->profile()->name()));

            linkHoveredConnection = connect(view->page(), &WebPage::linkHovered, this, [this](const QString &url) {
                if(!url.isEmpty())
                    emit showStatusMessage(url, 3000);
            });

            emit currentViewChanged(view);
        }
    });
}

SubWindow::~SubWindow()
{
    delete tabWidget;
}

WebView *SubWindow::currentView()
{
    return qobject_cast<WebView *>(tabWidget->currentWidget());
}

WebView *SubWindow::view(int index) const
{
    return qobject_cast<WebView *>(tabWidget->widget(index));
}

int SubWindow::tabCount() const
{
    return tabWidget->count();
}

void SubWindow::setProfile(WebProfile *profile)
{
    Q_CHECK_PTR(profile);
    this->m_profile = profile;
    for(int i = 0; i < tabWidget->count(); ++i) {
        auto *view = qobject_cast<WebView *>(tabWidget->widget(i));
        view->setProfile(profile);
    }
}

WebProfile *SubWindow::profile() const
{
    return m_profile;
}

int SubWindow::addTab(const QUrl &url, WebProfile *profile)
{
    auto *view = new WebView((profile == nullptr) ? m_profile : profile, this);
    if(!url.isEmpty())
        view->load(url);
    return tabWidget->addTab(view);
}

void SubWindow::setCurrentTab(int index)
{
    tabWidget->setCurrentIndex(index);
}