/*
 * 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 "webviewcontextmenu.h"
#include "webprofilemanager.h"
#include "webview.h"
#include <QContextMenuEvent>
#include <QDialog>
#include <QMenu>
#include <QSlider>
#include <QStatusBar>
#include <QStyle>
#include <QToolButton>
#include <QVBoxLayout>
#include <QWebEngineContextMenuData>
#include <QWebEngineHistory>
#include <QWidgetAction>

inline QAction *historyAction(QWebEngineView *view, const QWebEngineHistoryItem &item)
{
    QAction *action = new QAction(view);
    if(item.title().isEmpty())
        action->setText(item.url().toString());
    else
        action->setText(QObject::tr("%1 (%2)").arg(item.title(), item.url().toString()));

    QObject::connect(action, &QAction::triggered, view, [view, item]() {
        view->history()->goToItem(item);
    });
    return action;
}

WebViewContextMenu::WebViewContextMenu(WebView *view)
    : QMenu(view)
{
    setMinimumWidth(250);

    auto *navButtons = new QWidgetAction(this);

    auto *buttons = new QWidget(this);
    auto *buttonsLayout = new QHBoxLayout;
    buttonsLayout->setContentsMargins(8, 0, 8, 0);
    buttonsLayout->setSpacing(2);

    auto *backButton = new QToolButton(this);
    backButton->setEnabled(view->history()->canGoBack());
    backButton->setIcon(style()->standardIcon(QStyle::SP_ArrowBack));
    connect(backButton, &QToolButton::clicked, view, [this, view]() {
        view->back();
        this->close();
    });
    buttonsLayout->addWidget(backButton);

    auto *forwardButton = new QToolButton(this);
    forwardButton->setEnabled(view->history()->canGoForward());
    forwardButton->setIcon(style()->standardIcon(QStyle::SP_ArrowForward));
    connect(forwardButton, &QToolButton::clicked, view, [this, view]() {
        view->forward();
        this->close();
    });
    buttonsLayout->addWidget(forwardButton);

    auto *refreshButton = new QToolButton(this);
    refreshButton->setIcon(style()->standardIcon(QStyle::SP_BrowserReload));
    connect(refreshButton, &QToolButton::clicked, view, [view, this]() {
        view->reload();
        this->close();
    });
    buttonsLayout->addWidget(refreshButton);

    buttonsLayout->addStretch();

    auto *muteButton = new QToolButton(this);
    muteButton->setCheckable(true);
    muteButton->setChecked(view->page()->isAudioMuted());
    QIcon muteIcon;
    muteIcon.addPixmap(style()->standardPixmap(QStyle::SP_MediaVolume), QIcon::Normal, QIcon::Off);
    muteIcon.addPixmap(style()->standardPixmap(QStyle::SP_MediaVolumeMuted), QIcon::Normal, QIcon::On);
    muteButton->setIcon(muteIcon);
    connect(muteButton, &QToolButton::clicked, view, [view, this](bool checked) {
        view->page()->setAudioMuted(checked);
        this->close();
    });
    buttonsLayout->addWidget(muteButton);

    buttons->setLayout(buttonsLayout);
    navButtons->setDefaultWidget(buttons);

    this->addAction(navButtons);
    this->addSeparator();

    const auto ctxdata = view->page()->contextMenuData();

    if(ctxdata.mediaType() == QWebEngineContextMenuData::MediaTypeNone) {
        auto *backMenu = this->addMenu(tr("Back"));
        if(!view->history()->canGoBack()) {
            backMenu->setEnabled(false);
        } else {
            connect(backMenu, &QMenu::aboutToShow, view, [view, backMenu]() {
                backMenu->clear();
                const auto backItems = view->history()->backItems(10);
                for(const QWebEngineHistoryItem &item : backItems) {
                    backMenu->addAction(historyAction(view, item));
                }
            });
        }

        auto *forwardMenu = this->addMenu(tr("Forward"));
        if(!view->history()->canGoForward()) {
            forwardMenu->setEnabled(false);
        } else {
            connect(forwardMenu, &QMenu::aboutToShow, view, [view, forwardMenu]() {
                forwardMenu->clear();
                const auto forwardItems = view->history()->forwardItems(10);
                for(const QWebEngineHistoryItem &item : forwardItems) {
                    forwardMenu->addAction(historyAction(view, item));
                }
            });
        }

        connect(this->addAction(tr("Reload")), &QAction::triggered, view, [view]() {
            view->page()->triggerAction(QWebEnginePage::Reload);
        });
        connect(this->addAction(tr("Reload and bypass Cache")), &QAction::triggered, view, [view]() {
            view->page()->triggerAction(QWebEnginePage::ReloadAndBypassCache);
        });

        this->addSeparator();

        connect(this->addAction(tr("Select All")), &QAction::triggered, view, [view]() {
            view->page()->triggerAction(QWebEnginePage::SelectAll);
        });
        connect(this->addAction(tr("Clear Selection")), &QAction::triggered, view, [view]() {
            view->page()->triggerAction(QWebEnginePage::Unselect);
        });
        connect(this->addAction(tr("Copy to clipboard")), &QAction::triggered, view, [view]() {
            view->page()->triggerAction(QWebEnginePage::Copy);
        });

    } else if(ctxdata.mediaType() == QWebEngineContextMenuData::MediaTypeImage) {
        connect(this->addAction(tr("Copy image to clipboard")), &QAction::triggered, view, [view]() {
            view->page()->triggerAction(QWebEnginePage::CopyImageToClipboard);
        });
        connect(this->addAction(tr("Copy image URL to clipboard")), &QAction::triggered, view, [view]() {
            view->page()->triggerAction(QWebEnginePage::CopyImageUrlToClipboard);
        });
        if(!ctxdata.mediaUrl().isEmpty()) {
            if(view->url() != ctxdata.mediaUrl()) {
                connect(this->addAction(tr("Open image")), &QAction::triggered, view, [view, ctxdata]() {
                    view->load(ctxdata.mediaUrl());
                });
                connect(this->addAction(tr("Open image in new tab")), &QAction::triggered, view, [view, ctxdata]() {
                    view->createWindow(QWebEnginePage::WebBrowserTab)->load(ctxdata.mediaUrl());
                });
            }
            connect(this->addAction(tr("Save image")), &QAction::triggered, view, [view, ctxdata]() {
                view->page()->download(ctxdata.mediaUrl());
            });
        }

    } else {
        addMenu(view->page()->createStandardContextMenu());
    }

    if(!ctxdata.linkUrl().isEmpty()) {
        this->addSeparator();
        connect(this->addAction(tr("Open link in new tab")), &QAction::triggered, view, [view, ctxdata]() {
            view->createWindow(QWebEnginePage::WebBrowserTab)->load(ctxdata.linkUrl());
        });

        auto *newTabMenu = this->addMenu(tr("Open link in new tab with profile"));
        profileMenu(newTabMenu, [view, ctxdata](WebProfile *profile) {
            auto *v = view->createWindow(QWebEnginePage::WebBrowserTab);
            v->setProfile(profile);
            v->load(ctxdata.linkUrl());
        });

        connect(this->addAction(tr("Open link in new window")), &QAction::triggered, view, [view, ctxdata]() {
            view->createWindow(QWebEnginePage::WebBrowserWindow)->load(ctxdata.linkUrl());
        });

        connect(this->addAction(tr("Copy link address")), &QAction::triggered, view, [view]() {
            view->page()->triggerAction(QWebEnginePage::CopyLinkToClipboard);
        });
    }

    // zoom widget
    {
        this->addSeparator();

        auto *zoomSlider = new QSlider(Qt::Horizontal);
        zoomSlider->setMinimum(5);
        zoomSlider->setMaximum(50);
        zoomSlider->setValue(static_cast<int>(view->zoomFactor() * 10));

        auto *zoomAction = this->addAction(tr("Zoom: %1x").arg(view->zoomFactor()));
        connect(zoomAction, &QAction::triggered, view, [zoomSlider]() {
            zoomSlider->setValue(10);
        });

        connect(zoomSlider, &QSlider::valueChanged, view, [view, zoomAction](int value) {
            zoomAction->setText(tr("Zoom: %1x").arg(static_cast<qreal>(value) / 10));
            view->setZoomFactor(static_cast<qreal>(value) / 10);
        });

        auto *zoomWidgetAction = new QWidgetAction(this);
        zoomWidgetAction->setDefaultWidget(zoomSlider);

        this->addAction(zoomWidgetAction);
    }

#ifndef NDEBUG
    /*
    {
        this->addSeparator();
        auto *autofillAction = this->addAction(tr("Autofill form"));
        connect(autofillAction, &QAction::triggered, view, [view]() {
            Wallet::autocompleteForm(view);
        });
    };
    */
#endif
}