/*
 * 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 "profileview.h"
#include "ui_profileview.h"
#include <profileinterface.h>
#include <QWebEngineSettings>
#include <QWebEngineCookieStore>
#include <QDateTime>
#include "newhttpheaderdialog.h"

inline void connectSetting(QCheckBox *checkBox, Profile *profile, QWebEngineSettings::WebAttribute attr)
{
    checkBox->setChecked(profile->settings()->testAttribute(attr));
    QObject::connect(checkBox, &QCheckBox::clicked, [profile, attr](bool checked) {
        profile->settings()->setAttribute(attr, checked);
        emit profile->attributeChanged(attr, checked);
    });
}

ProfileView::ProfileView(Profile *profile, QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::ProfileView)
{
    Q_CHECK_PTR(profile);
    m_profile = profile;
    ui->setupUi(this);

    // general tab
    ui->name->setText(profile->name());
    connect(ui->name, &QLineEdit::editingFinished, profile, [=]() {
        profile->setName(ui->name->text());
    });

    ui->offTheRecord->setChecked(profile->isOffTheRecord());

    ui->homepage->setText(profile->homepage().toString());
    connect(ui->homepage, &QLineEdit::editingFinished, profile, [=]() {
        profile->setHomepage(QUrl::fromUserInput(ui->homepage->text()));
    });

    ui->newtab->setText(profile->newtab().toString());
    connect(ui->newtab, &QLineEdit::editingFinished, profile, [=]() {
        profile->setNewtab(QUrl::fromUserInput(ui->newtab->text()));
    });

    ui->search->setText(profile->search());
    connect(ui->search, &QLineEdit::editingFinished, profile, [=]() {
        profile->setSearch(ui->search->text());
    });

    // http tab
    ui->userAgent->setPlainText(m_profile->httpUserAgent());
    connect(ui->userAgent, &QPlainTextEdit::textChanged, profile, [=]() {
        profile->setHttpUserAgent(ui->userAgent->toPlainText());
    });

    ui->acceptLanguage->setPlainText(m_profile->httpAcceptLanguage());
    connect(ui->acceptLanguage, &QPlainTextEdit::textChanged, profile, [=]() {
        profile->setHttpAcceptLanguage(ui->acceptLanguage->toPlainText());
    });

    ui->cacheType->setCurrentIndex(m_profile->httpCacheType());
    connect(ui->cacheType, QOverload<int>::of(&QComboBox::currentIndexChanged), profile, [=](int index) {
        profile->setHttpCacheType(index);
    });

    ui->cacheSize->setText(QString::number(m_profile->httpCacheMaximumSize()));
    connect(ui->cacheSize, &QLineEdit::textChanged, profile, [=](const QString &text) {
        profile->setHttpCacheMaximumSize(text.toInt());
    });

    ui->cookiePolicy->setCurrentIndex(m_profile->persistentCookiesPolicy());
    connect(ui->cookiePolicy, QOverload<int>::of(&QComboBox::currentIndexChanged), profile, [=](int index) {
        profile->setPersistentCookiesPolicy(index);
    });

    connect(ui->clearCache_pushButton, &QPushButton::clicked, profile, &QWebEngineProfile::clearHttpCache);
    connect(ui->clearHistory_pushButton, &QPushButton::clicked, profile, &QWebEngineProfile::clearAllVisitedLinks);

    ui->storagePath_lineEdit->setText(m_profile->persistentStoragePath());
    ui->cachePath_lineEdit->setText(m_profile->cachePath());

    // headers tab
    for(auto i = m_profile->headers().constBegin(); i != m_profile->headers().constEnd(); ++i) {
        //ui->httpHeaders->addItem();
        headerChanged(i.key(), i.value());
    }
    connect(m_profile, &Profile::headerChanged, this, &ProfileView::headerChanged);
    connect(m_profile, &Profile::headerRemoved, this, &ProfileView::headerRemoved);
    connect(ui->headers_insert, &QPushButton::clicked, m_profile, [this]() {
        auto *dlg = new NewHttpHeaderDialog(this);
        if(dlg->exec() == QDialog::Accepted) {
            m_profile->setHttpHeader(dlg->header(), dlg->value());
        }
        delete dlg;
    });
    connect(ui->headers_delete, &QPushButton::clicked, m_profile, [this]() {
        for(auto &list : ui->httpHeaders->selectedRanges()) {
            for(int i = list.bottomRow(); i >= list.topRow(); --i) {
                m_profile->removeHttpHeader(ui->httpHeaders->item(i, 0)->text());
            }
        }
    });

    // settings tab
    connectSetting(ui->autoloadImages, m_profile, QWebEngineSettings::AutoLoadImages);
    connectSetting(ui->autoloadIcons, m_profile, QWebEngineSettings::AutoLoadIconsForPage);

    connectSetting(ui->javascriptEnabled, m_profile, QWebEngineSettings::JavascriptEnabled);
    connectSetting(ui->javascriptCanAccessClipboard, m_profile, QWebEngineSettings::JavascriptCanAccessClipboard);
    connectSetting(ui->javascriptCanOpenWindows, m_profile, QWebEngineSettings::JavascriptCanOpenWindows);
    connectSetting(ui->javascriptCanActivateWindows, m_profile, QWebEngineSettings::AllowWindowActivationFromJavaScript);

    connectSetting(ui->linksIncludedInFocusChain, m_profile, QWebEngineSettings::LinksIncludedInFocusChain);
    connectSetting(ui->spatialNavigationEnabled, m_profile, QWebEngineSettings::SpatialNavigationEnabled);
    connectSetting(ui->focusOnNavigationEnabled, m_profile, QWebEngineSettings::FocusOnNavigationEnabled);
    connectSetting(ui->touchIconsEnabled, m_profile, QWebEngineSettings::TouchIconsEnabled);

    connectSetting(ui->showScrollBars, m_profile, QWebEngineSettings::ShowScrollBars);
    connectSetting(ui->scrollAnimatorEnabled, m_profile, QWebEngineSettings::ScrollAnimatorEnabled);
    connectSetting(ui->errorPagesEnabled, m_profile, QWebEngineSettings::ErrorPageEnabled);

    connectSetting(ui->localContentCanAccessRemoteUrls, m_profile, QWebEngineSettings::LocalContentCanAccessRemoteUrls);
    connectSetting(ui->localContentCanAccessFileUrls, m_profile, QWebEngineSettings::LocalContentCanAccessFileUrls);

    connectSetting(ui->localStorageEnabled, m_profile, QWebEngineSettings::LocalStorageEnabled);
    connectSetting(ui->webglEnabled, m_profile, QWebEngineSettings::WebGLEnabled);
    connectSetting(ui->canvasEnabled, m_profile, QWebEngineSettings::Accelerated2dCanvasEnabled);

    connectSetting(ui->xssAuditingEnabled, m_profile, QWebEngineSettings::XSSAuditingEnabled);
    connectSetting(ui->hyperlinkAuditingEnabled, m_profile, QWebEngineSettings::HyperlinkAuditingEnabled);

    connectSetting(ui->allowRunningInsecureContent, m_profile, QWebEngineSettings::AllowRunningInsecureContent);
    connectSetting(ui->allowGeolocationOnInsecureContent, m_profile, QWebEngineSettings::AllowGeolocationOnInsecureOrigins);
    connectSetting(ui->ppapiPluginsEnabled, m_profile, QWebEngineSettings::PluginsEnabled);
    connectSetting(ui->fullscreenSupportEnabled, m_profile, QWebEngineSettings::FullScreenSupportEnabled);
    connectSetting(ui->screenCaptureEnabled, m_profile, QWebEngineSettings::ScreenCaptureEnabled);
    connectSetting(ui->printElementBackgrounds, m_profile, QWebEngineSettings::PrintElementBackgrounds);

    // cookies tab
    loadCookies(profile->cookieStore());
    for(const auto &c : profile->cookies()) {
        cookieAdded(c);
    }
}

ProfileView::~ProfileView()
{
    delete ui;
}

void ProfileView::loadCookies(QWebEngineCookieStore *store)
{
    //
    connect(store, &QWebEngineCookieStore::cookieAdded, this, &ProfileView::cookieAdded);
    connect(store, &QWebEngineCookieStore::cookieRemoved, this, &ProfileView::cookieRemoved);

    connect(ui->cookies_reload, &QPushButton::clicked, store, [=]() {
        ui->cookies->clearContents();
        ui->cookies->setRowCount(0);
        store->loadAllCookies();
    });

    connect(ui->cookies_delete, &QPushButton::clicked, store, [=]() {
        for(auto &list : ui->cookies->selectedRanges()) {
            for(int i = list.bottomRow(); i >= list.topRow(); --i) {
                auto cookie = ui->cookies->item(i, 0)->data(Qt::UserRole).value<QNetworkCookie>();
                store->deleteCookie(cookie);
            }
        }
    });
    connect(ui->cookies_deleteSession, &QPushButton::clicked, store, &QWebEngineCookieStore::deleteSessionCookies);
    connect(ui->cookies_deleteAll, &QPushButton::clicked, store, &QWebEngineCookieStore::deleteAllCookies);
}

void ProfileView::headerChanged(const QString &name, const QString &value)
{
    const auto items = ui->httpHeaders->findItems(name, Qt::MatchExactly);
    if(!items.isEmpty()) {
        QTableWidgetItem *valueItem = ui->httpHeaders->item(items.constFirst()->row(), 1);
        valueItem->setText(value);
    } else {
        // new header
        const int index = ui->httpHeaders->rowCount();
        ui->httpHeaders->setRowCount(index + 1);
        ui->httpHeaders->setItem(index, 0, new QTableWidgetItem(name));
        ui->httpHeaders->setItem(index, 1, new QTableWidgetItem(value));
    }
}

void ProfileView::headerRemoved(const QString& name)
{
    const auto items = ui->httpHeaders->findItems(name, Qt::MatchExactly);
    if(!items.isEmpty()) {
        ui->httpHeaders->removeRow(items.constFirst()->row());
    }
}

void ProfileView::cookieAdded(const QNetworkCookie &cookie)
{
    auto index = ui->cookies->rowCount();
    ui->cookies->setRowCount(index + 1);

    auto *item = new QTableWidgetItem(QString(cookie.name()));
    item->setData(Qt::UserRole, QVariant::fromValue(cookie));
    ui->cookies->setItem(index, 0, item);
    ui->cookies->setItem(index, 1, new QTableWidgetItem(cookie.domain()));
    ui->cookies->setItem(index, 2, new QTableWidgetItem(cookie.path()));
    if(cookie.isSessionCookie())
        ui->cookies->setItem(index, 3, new QTableWidgetItem(tr("session")));
    else
        ui->cookies->setItem(index, 3, new QTableWidgetItem(cookie.expirationDate().toString(Qt::RFC2822Date)));
}

void ProfileView::cookieRemoved(const QNetworkCookie &cookie)
{
    for(int i = 0; i < ui->cookies->rowCount(); ++i) {
        auto *item = ui->cookies->item(i, 0);
        if(item->data(Qt::UserRole).value<QNetworkCookie>() == cookie) {
            //qDebug("removing cookie on row %i", i);
            ui->cookies->removeRow(i);
            break;
        }
    }
}