/*
 * Copyright 2022-2024 Soren Stoutner <soren@stoutner.com>.
 *
 * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc/>.
 *
 * Privacy Browser PC is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Privacy Browser PC is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
 */

// Application headers.
#include "UrlRequestInterceptor.h"
#include "GlobalVariables.h"
#include "helpers/FilterListHelper.h"
#include "structs/RequestStruct.h"

// KDE Framework headers.
#include <KLocalizedString>

// Construct the class.
UrlRequestInterceptor::UrlRequestInterceptor(PrivacyWebEngineView *privacyWebEngineViewPointer) :
                                             QWebEngineUrlRequestInterceptor(privacyWebEngineViewPointer), privacyWebEngineViewPointer(privacyWebEngineViewPointer) {}

void UrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &urlRequestInfo)
{
    // Clear the requests list if a main frame resource is being loaded.
    if (urlRequestInfo.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeMainFrame)
        emit newMainFrameResource();

    // Create a requests struct.
    RequestStruct *requestStructPointer = new RequestStruct;

    // Store the basic request information.
    requestStructPointer->navigationTypeInt = urlRequestInfo.navigationType();
    requestStructPointer->requestMethodString = urlRequestInfo.requestMethod();
    requestStructPointer->resourceTypeInt = urlRequestInfo.resourceType();
    requestStructPointer->urlString = urlRequestInfo.requestUrl().toString();
    requestStructPointer->webPageUrlString = urlRequestInfo.firstPartyUrl().toString();

    // Check the filter lists.
    bool continueProcessing = globalFilterListHelperPointer->checkFilterLists(privacyWebEngineViewPointer, urlRequestInfo, requestStructPointer);

    // Further process the request if it hasn't already been handled.
    if (continueProcessing) {
        // Handle the request according to the resource type.
        switch (urlRequestInfo.resourceType())
        {
            // A naughty HTTP ping request.
            case QWebEngineUrlRequestInfo::ResourceTypePing:
            {
                // Block the HTTP ping request.
                urlRequestInfo.block(true);

                // Mark the request struct as blocked.
                requestStructPointer->dispositionInt = FilterListHelper::BLOCKED;

                // Mark the ping as blocked by the default behavior.
                requestStructPointer->filterListTitle = i18nc("Default HTTP ping blocking", "Default blocking of all HTTP ping requests.");

                // Display the HTTP Ping blocked dialog.
                emit displayHttpPingDialog(urlRequestInfo.requestUrl().toString());

                break;
            }

            default:
            {
                // Do nothing.
                break;
            }
        }
    }

    // Handle the request according to the navigation type.
    switch (urlRequestInfo.navigationType())
    {
        case QWebEngineUrlRequestInfo::NavigationTypeLink:
        case QWebEngineUrlRequestInfo::NavigationTypeTyped:
        case QWebEngineUrlRequestInfo::NavigationTypeBackForward:
        // case QWebEngineUrlRequestInfo::NavigationTypeReload:  This can be uncommented once https://redmine.stoutner.com/issues/821 has been fixed.
        case QWebEngineUrlRequestInfo::NavigationTypeRedirect:
        {
            // Only check the hosts if the main URL is changing.
            if (urlRequestInfo.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeMainFrame)
            {
                // Get the hosts.
                QString requestingHost = urlRequestInfo.initiator().host();
                QString requestedHost = urlRequestInfo.requestUrl().host();

                // Reapply the domain settings if the host is changing.
                if (requestingHost != requestedHost)
                    emit applyDomainSettings(requestedHost);
            }

            break;
        }

        default:
            // Do nothing.
            break;
    }

    // Send the request struct to the privacy WebEngine view.
    emit requestProcessed(requestStructPointer);
}
