/*
    This file is part of the KDE project.

    SPDX-FileCopyrightText: 2021 Stefano Crocco <stefano.crocco@alice.it>

    SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/

#ifndef WEBENGINEPARTCONTROLS_H
#define WEBENGINEPARTCONTROLS_H

#include <QObject>
#include <QWebEngineCertificateError>

#include <kwebenginepartlib_export.h>

class QWebEngineProfile;
class QWebEngineScript;

class WebEnginePartCookieJar;
class SpellCheckerManager;
class WebEnginePartDownloadManager;
class WebEnginePage;
class NavigationRecorder;

namespace KonqWebEnginePart {
    class CertificateErrorDialogManager;
}

class KWEBENGINEPARTLIB_EXPORT WebEnginePartControls : public QObject
{
    Q_OBJECT

public:

    static WebEnginePartControls *self();

    ~WebEnginePartControls();

    bool isReady() const;

    void setup(QWebEngineProfile *profile);

    SpellCheckerManager* spellCheckerManager() const;

    WebEnginePartDownloadManager* downloadManager() const;

    NavigationRecorder* navigationRecorder() const;

    bool handleCertificateError(const QWebEngineCertificateError &ce, WebEnginePage *page);

    QString httpUserAgent() const;

    QString defaultHttpUserAgent() const;

    void setHttpUserAgent(const QString &uaString);

private slots:
    void reparseConfiguration();

signals:
    void userAgentChanged(const QString &uaString);

private:

    WebEnginePartControls();

    /**
     * @brief Constructs an `Accept-Language` http header from the language settings
     *
     * The accepted languages are determined according to the following sources:
     * - the language settings in the application itself (using the `Application Language...` menu entry)
     * - the language settings in `SystemSettings`
     * - the locale returned by `QLocale::system()`
     *
     * These sources are tried in order: the first to return a valid value is used. If all return an invalid
     * value (which shouldn't happen), an empty string is returned.
     * @return a suitable `AcceptLanguage` header according to the user preferences
     */
    QString determineHttpAcceptLanguageHeader() const;

    /**
     * @brief Inserts in the profile script collection the scripts described in the `:/scripts.json` file
     *
     * The `:/scripts.json` file should contain information about all scripts needed to be injected in each
     * HTML document (for example, the one used by WebEngineWallet to detect forms).
     *
     * The `:scripts.json` file should have the following structure:
     * @code{.json}
     * {
     *      "first script name": {
     *          "file": "path to first script file",
     *          "injectionPoint": injectionPointAsInt,
     *          "worldId": worldIdAsInt,
     *          "runsOnSubFrames": true
     *      },
     *      "second script name": {
     *         ...
     *      },
     *      ...
     * }
     * @endcode
     * Each script is represented by the one of the inner objects. The corresponding key can be anything and
     * represents a name by which the script can be recognized. It's passed to `QWebEngineScript::setName()`.
     * The keys of the object representing a script have the following meaning:
     * - `"file"`: it's the path of the file containing the actual source code of the script. It usually refers
     * to a `qrc` resource
     * - `"injectionPoint"` (optional): it's the script injection point, as described by `QWebEngineScript::InjectionPoint`.
     *  it should be one of the values of the enum. If not given, the default injection point is used. If an invalid value
     *  is given, the behavior is undefined
     * - `"worldId"` (optional): it's the world id where the script should be registered. It's passed to `QWebEngineScript::setWorldId()`
     *  If not given, the default application world is used. If a negative value is given, the behavior is undefined
     * - `"runsOnSubFrames" (optional): if given, it's passed to `QWebEngineScript::setRunsOnSubFrames`
     */
    void registerScripts();

    /**
     * @brief Creates a QWebEngineScript from it's JSON description and its name
     * @param name the name to give to the script (will be passed to QWebEngineScript::setName()
     * @param obj the JSON object describing the script
     * @return the script object
     * @see registerScripts() for the description of the fields in @p object
     */
    static QWebEngineScript scriptFromJson(const QString &name, const QJsonObject &obj);

    QWebEngineProfile *m_profile;
    WebEnginePartCookieJar *m_cookieJar;
    SpellCheckerManager *m_spellCheckerManager;
    WebEnginePartDownloadManager *m_downloadManager;
    KonqWebEnginePart::CertificateErrorDialogManager *m_certificateErrorDialogManager;
    NavigationRecorder *m_navigationRecorder;
    QString m_defaultUserAgent;
};

#endif // WEBENGINEPARTCONTROLS_H
