/*
 * SPDX-FileCopyrightText: Copyright 2025 Open Mobile Platform LLC <community@omp.ru>
 * SPDX-License-Identifier: Proprietary
 */

#pragma once

#include <memory>

#include <QJSValue>
#include <QObject>
#include <QVariant>

#include "browserextension.h"

namespace Aurora {
namespace WebView {

/**
 * @class IJavaScriptHandler
 * @brief Used to call native C++ code from JS on webpage.
 *
 * WebView supports calling native functions from JS context via `executeNative()`.
 * Use this interface to implement your handler and register it in IJavaScriptExtension
 * with `IJavaScriptExtension::setJavaScriptHandler()`.
 */
class IJavaScriptHandler
{
public:
    /// @brief default destructor
    virtual ~IJavaScriptHandler() = default;

    /// @brief handle JavaScript "executeNative" function call
    /// @param name name of the call to identify it
    /// @param data arguments that were forwarded from JavaScript call
    /// @return a value which will be forwarded to the JavaScript side
    /// as a return value for "executeNative" function call
    virtual QVariant executeNative(const QString &name, const QVariant &data) = 0;
};

/**
 * @class IJavaScriptExtension
 * @brief Allows working with JavaScript.
 *
 * This extension provides the following functionality:
 * 1. JavaScript code execution (with/without results returned)
 * 2. Message exchange between native C++/QML and webpage JS code
 *
 */
class IJavaScriptExtension : public QObject, public Cef::BrowserExtension
{
    Q_OBJECT
public:
    IJavaScriptExtension(Cef::Browser &browser)
        : Cef::BrowserExtension(browser)
    {}
    /// @brief default destructor
    virtual ~IJavaScriptExtension() = default;

    /// @brief execute JavaScript code without ability to process return value (run and forget)
    /// @param script JavaScript code to execute
    virtual void executeJavaScript(const QString &script) = 0;

    /// @brief add message listener for asynchronous messages
    /// @param name name of the message
    virtual void addMessageListener(const QString &name) = 0;

    // should be removed
    virtual bool findMessageListener(const QString &name) = 0;

    /// @brief execute JavaScript code
    /// @param script JavaScript code to execute
    /// @param callback callback which will be executed in the success case
    /// @param errorCallback callback which will be executed in the error case
    virtual void runJavaScript(
        const QString &script, const QJSValue &callback, const QJSValue &errorCallback)
        = 0;

    /// @brief set JavaScript handler
    ///
    /// This handler is used when JavaScript "executeNative" function is called
    /// @param handler handler to set
    virtual void setJavaScriptHandler(std::shared_ptr<IJavaScriptHandler> handler) = 0;

    /// @brief get JavaScript handler
    /// @return JavaScript handler instance
    virtual std::shared_ptr<IJavaScriptHandler> javaScriptHandler() const = 0;
};

} // namespace WebView
} // namespace Aurora
