// <copyright file="JavaScriptEngine.cs" company="Selenium Committers">
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
// </copyright>

using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text.Json;
using OpenQA.Selenium.DevTools;
using OpenQA.Selenium.Internal;

namespace OpenQA.Selenium;

/// <summary>
/// Provides methods allowing the user to manage settings in the browser's JavaScript engine.
/// </summary>
[RequiresUnreferencedCode("JavaScriptEngine is currently implemented with CDP. When it is implemented with BiDi, AOT will be supported")]
[RequiresDynamicCode("JavaScriptEngine is currently implemented with CDP. When it is implemented with BiDi, AOT will be supported.")]
public class JavaScriptEngine : IJavaScriptEngine
{
    private const string MonitorBindingName = "__webdriver_attribute";

    private readonly IWebDriver driver;
    private readonly Lazy<DevToolsSession> session;
    private readonly Dictionary<string, InitializationScript> initializationScripts = new Dictionary<string, InitializationScript>();
    private readonly Dictionary<string, PinnedScript> pinnedScripts = new Dictionary<string, PinnedScript>();
    private readonly HashSet<string> bindings = new HashSet<string>();
    private bool isEnabled = false;
    private bool isDisposed = false;

    /// <summary>
    /// Initializes a new instance of the <see cref="JavaScriptEngine"/> class.
    /// </summary>
    /// <param name="driver">The <see cref="IWebDriver"/> instance in which the JavaScript engine is executing.</param>
    public JavaScriptEngine(IWebDriver driver)
    {
        // Use of Lazy<T> means this exception won't be thrown until the user first
        // attempts to access the DevTools session, probably on the first call to
        // StartEventMonitoring() or in adding scripts to the instance.
        this.driver = driver;
        this.session = new Lazy<DevToolsSession>(() =>
        {
            if (driver is not IDevTools devToolsDriver)
            {
                throw new WebDriverException("Driver must implement IDevTools to use these features");
            }

            return devToolsDriver.GetDevToolsSession();
        });
    }

    /// <summary>
    /// Occurs when a JavaScript callback with a named binding is executed.
    /// </summary>
    public event EventHandler<JavaScriptCallbackExecutedEventArgs>? JavaScriptCallbackExecuted;

    /// <summary>
    /// Occurs when an exception is thrown by JavaScript being executed in the browser.
    /// </summary>
    public event EventHandler<JavaScriptExceptionThrownEventArgs>? JavaScriptExceptionThrown;

    /// <summary>
    /// Occurs when methods on the JavaScript console are called.
    /// </summary>
    public event EventHandler<JavaScriptConsoleApiCalledEventArgs>? JavaScriptConsoleApiCalled;

    /// <summary>
    /// Occurs when a value of an attribute in an element is being changed.
    /// </summary>
    public event EventHandler<DomMutatedEventArgs>? DomMutated;

    /// <summary>
    /// Gets the read-only list of initialization scripts added for this JavaScript engine.
    /// </summary>
    public IReadOnlyList<InitializationScript> InitializationScripts
    {
        get
        {
            // Return a copy.
            return new List<InitializationScript>(this.initializationScripts.Values);
        }
    }

    /// <summary>
    /// Gets the read-only list of bindings added for this JavaScript engine.
    /// </summary>
    public IReadOnlyList<string> ScriptCallbackBindings
    {
        get
        {
            // Return a copy.
            return new List<string>(this.bindings);
        }
    }

    /// <summary>
    /// Asynchronously starts monitoring for events from the browser's JavaScript engine.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    public async Task StartEventMonitoring()
    {
        this.session.Value.Domains.JavaScript.BindingCalled += OnScriptBindingCalled;
        this.session.Value.Domains.JavaScript.ExceptionThrown += OnJavaScriptExceptionThrown;
        this.session.Value.Domains.JavaScript.ConsoleApiCalled += OnConsoleApiCalled;
        await this.EnableDomains().ConfigureAwait(false);
    }

    /// <summary>
    /// Stops monitoring for events from the browser's JavaScript engine.
    /// </summary>
    public void StopEventMonitoring()
    {
        this.session.Value.Domains.JavaScript.ConsoleApiCalled -= OnConsoleApiCalled;
        this.session.Value.Domains.JavaScript.ExceptionThrown -= OnJavaScriptExceptionThrown;
        this.session.Value.Domains.JavaScript.BindingCalled -= OnScriptBindingCalled;
    }

    /// <summary>
    /// Enables monitoring for DOM changes.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    public async Task EnableDomMutationMonitoring()
    {
        // Execute the script to have it enabled on the currently loaded page.
        string script = ResourceUtilities.MutationListenerAtom;
        await this.session.Value.Domains.JavaScript.Evaluate(script).ConfigureAwait(false);

        await this.AddScriptCallbackBinding(MonitorBindingName).ConfigureAwait(false);
        await this.AddInitializationScript(MonitorBindingName, script).ConfigureAwait(false);
    }

    /// <summary>
    /// Disables monitoring for DOM changes.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    public async Task DisableDomMutationMonitoring()
    {
        await this.RemoveScriptCallbackBinding(MonitorBindingName).ConfigureAwait(false);
        await this.RemoveInitializationScript(MonitorBindingName).ConfigureAwait(false);
    }

    /// <summary>
    /// Asynchronously adds JavaScript to be loaded on every document load.
    /// </summary>
    /// <param name="scriptName">The friendly name by which to refer to this initialization script.</param>
    /// <param name="script">The JavaScript to be loaded on every page.</param>
    /// <returns>A task containing an <see cref="InitializationScript"/> object representing the script to be loaded on each page.</returns>
    /// <exception cref="ArgumentNullException">If <paramref name="scriptName"/> or <paramref name="script"/> are <see langword="null"/>.</exception>
    public async Task<InitializationScript> AddInitializationScript(string scriptName, [StringSyntax(StringSyntaxConstants.JavaScript)] string script)
    {
        if (scriptName is null)
        {
            throw new ArgumentNullException(nameof(scriptName));
        }

        if (script is null)
        {
            throw new ArgumentNullException(nameof(script));
        }

        if (this.initializationScripts.TryGetValue(scriptName, out InitializationScript? existingScript))
        {
            return existingScript;
        }

        await this.EnableDomains().ConfigureAwait(false);

        string scriptId = await this.session.Value.Domains.JavaScript.AddScriptToEvaluateOnNewDocument(script).ConfigureAwait(false);

        InitializationScript initializationScript = new InitializationScript(scriptId, scriptName, script);
        this.initializationScripts[scriptName] = initializationScript;
        return initializationScript;
    }

    /// <summary>
    /// Asynchronously removes JavaScript from being loaded on every document load.
    /// </summary>
    /// <param name="scriptName">The friendly name of the initialization script to be removed.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    /// <exception cref="ArgumentNullException">If <paramref name="scriptName"/> is <see langword="null"/>.</exception>
    public async Task RemoveInitializationScript(string scriptName)
    {
        if (scriptName is null)
        {
            throw new ArgumentNullException(nameof(scriptName));
        }

        if (this.initializationScripts.TryGetValue(scriptName, out InitializationScript? script))
        {
            string scriptId = script.ScriptId;
            await this.session.Value.Domains.JavaScript.RemoveScriptToEvaluateOnNewDocument(scriptId).ConfigureAwait(false);
            this.initializationScripts.Remove(scriptName);
        }
    }

    /// <summary>
    /// Asynchronously removes all initialization scripts from being loaded on every document load.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    public async Task ClearInitializationScripts()
    {
        // Use a copy of the list to prevent the iterator from becoming invalid
        // when we modify the collection.
        List<string> scriptNames = new List<string>(this.initializationScripts.Keys);
        foreach (string scriptName in scriptNames)
        {
            await this.RemoveInitializationScript(scriptName).ConfigureAwait(false);
        }
    }

    /// <summary>
    /// Pins a JavaScript snippet for execution in the browser without transmitting the
    /// entire script across the wire for every execution.
    /// </summary>
    /// <param name="script">The JavaScript to pin</param>
    /// <returns>A task containing a <see cref="PinnedScript"/> object to use to execute the script.</returns>
    /// <exception cref="ArgumentNullException">If <paramref name="script"/> is <see langword="null"/>.</exception>
    public async Task<PinnedScript> PinScript([StringSyntax(StringSyntaxConstants.JavaScript)] string script)
    {
        if (script == null)
        {
            throw new ArgumentNullException(nameof(script));
        }

        string newScriptHandle = Guid.NewGuid().ToString("N");

        // We do an "Evaluate" first so as to immediately create the script on the loaded
        // page, then will add it to the initialization of future pages.
        await this.EnableDomains().ConfigureAwait(false);

        string creationScript = PinnedScript.MakeCreationScript(newScriptHandle, script);
        await this.session.Value.Domains.JavaScript.Evaluate(creationScript).ConfigureAwait(false);
        string scriptId = await this.session.Value.Domains.JavaScript.AddScriptToEvaluateOnNewDocument(creationScript).ConfigureAwait(false);

        PinnedScript pinnedScript = new PinnedScript(script, newScriptHandle, scriptId);
        this.pinnedScripts[pinnedScript.Handle] = pinnedScript;
        return pinnedScript;
    }

    /// <summary>
    /// Unpins a previously pinned script from the browser.
    /// </summary>
    /// <param name="script">The <see cref="PinnedScript"/> object to unpin.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    /// <exception cref="ArgumentNullException">If <paramref name="script"/> is <see langword="null"/>.</exception>
    public async Task UnpinScript(PinnedScript script)
    {
        if (script == null)
        {
            throw new ArgumentNullException(nameof(script));
        }

        if (this.pinnedScripts.ContainsKey(script.Handle))
        {
            await this.session.Value.Domains.JavaScript.Evaluate(script.MakeRemovalScript()).ConfigureAwait(false);
            await this.session.Value.Domains.JavaScript.RemoveScriptToEvaluateOnNewDocument(script.ScriptId).ConfigureAwait(false);
            this.pinnedScripts.Remove(script.Handle);
        }
    }

    /// <summary>
    /// Asynchronously adds a binding to a callback method that will raise an event when the named
    /// binding is called by JavaScript executing in the browser.
    /// </summary>
    /// <param name="bindingName">The name of the callback that will trigger events when called by JavaScript executing in the browser.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    /// <exception cref="ArgumentNullException">If <paramref name="bindingName"/> is <see langword="null"/>.</exception>
    /// <exception cref="ArgumentException">If A binding with the specified name already exists.</exception>
    public async Task AddScriptCallbackBinding(string bindingName)
    {
        if (bindingName is null)
        {
            throw new ArgumentNullException(nameof(bindingName));
        }

        if (!this.bindings.Add(bindingName))
        {
            throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "A binding named {0} has already been added", bindingName));
        }

        await this.EnableDomains().ConfigureAwait(false);
        await this.session.Value.Domains.JavaScript.AddBinding(bindingName).ConfigureAwait(false);
    }

    /// <summary>
    /// Asynchronously removes a binding to a JavaScript callback.
    /// </summary>
    /// <param name="bindingName">The name of the callback to be removed.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    /// <exception cref="ArgumentNullException">If <paramref name="bindingName"/> is <see langword="null"/>.</exception>
    public async Task RemoveScriptCallbackBinding(string bindingName)
    {
        if (bindingName is null)
        {
            throw new ArgumentNullException(nameof(bindingName));
        }

        await this.session.Value.Domains.JavaScript.RemoveBinding(bindingName).ConfigureAwait(false);
        _ = this.bindings.Remove(bindingName);
    }

    /// <summary>
    /// Asynchronously removes all bindings to JavaScript callbacks.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    public async Task ClearScriptCallbackBindings()
    {
        // Use a copy of the list to prevent the iterator from becoming invalid
        // when we modify the collection.
        List<string> bindingList = new List<string>(this.bindings);
        foreach (string binding in bindingList)
        {
            await this.RemoveScriptCallbackBinding(binding).ConfigureAwait(false);
        }
    }

    /// <summary>
    /// Asynchronously removes all bindings to JavaScript callbacks, all
    /// initialization scripts from being loaded for each document, and unpins
    /// all pinned scripts.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    public async Task ClearAll()
    {
        await this.ClearPinnedScripts().ConfigureAwait(false);
        await this.ClearInitializationScripts().ConfigureAwait(false);
        await this.ClearScriptCallbackBindings().ConfigureAwait(false);
    }

    /// <summary>
    /// Asynchronously removes all bindings to JavaScript callbacks, all
    /// initialization scripts from being loaded for each document, all
    /// pinned scripts, and stops listening for events.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    public async Task Reset()
    {
        this.StopEventMonitoring();
        await ClearAll().ConfigureAwait(false);
    }

    /// <summary>
    /// Releases all resources associated with this <see cref="JavaScriptEngine"/>.
    /// </summary>
    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// Releases all resources associated with this <see cref="JavaScriptEngine"/>.
    /// </summary>
    /// <param name="disposing"><see langword="true"/> if the Dispose method was explicitly called; otherwise, <see langword="false"/>.</param>
    protected virtual void Dispose(bool disposing)
    {
        if (!this.isDisposed)
        {
            if (disposing)
            {
                if (this.session.IsValueCreated)
                {
                    this.session.Value.Dispose();
                }
            }

            this.isDisposed = true;
        }
    }

    private async Task ClearPinnedScripts()
    {
        // Use a copy of the list to prevent the iterator from becoming invalid
        // when we modify the collection.
        List<string> scriptHandles = new List<string>(this.pinnedScripts.Keys);
        foreach (string scriptHandle in scriptHandles)
        {
            await this.UnpinScript(this.pinnedScripts[scriptHandle]).ConfigureAwait(false);
        }
    }

    private async Task EnableDomains()
    {
        if (!this.isEnabled)
        {
            await this.session.Value.Domains.JavaScript.EnablePage().ConfigureAwait(false);
            await this.session.Value.Domains.JavaScript.EnableRuntime().ConfigureAwait(false);
            this.isEnabled = true;
        }
    }

    private void OnScriptBindingCalled(object? sender, BindingCalledEventArgs e)
    {
        if (e.Name == MonitorBindingName)
        {
            DomMutationData valueChangeData = JsonSerializer.Deserialize<DomMutationData>(e.Payload) ?? throw new JsonException("DomMutationData returned null");
            var locator = By.CssSelector($"*[data-__webdriver_id='{valueChangeData.TargetId}']");
            valueChangeData.Element = driver.FindElements(locator).FirstOrDefault();

            this.DomMutated?.Invoke(this, new DomMutatedEventArgs(valueChangeData));
        }

        this.JavaScriptCallbackExecuted?.Invoke(this, new JavaScriptCallbackExecutedEventArgs
        (
            scriptPayload: e.Payload,
            bindingName: e.Name
        ));
    }

    private void OnJavaScriptExceptionThrown(object? sender, ExceptionThrownEventArgs e)
    {
        this.JavaScriptExceptionThrown?.Invoke(this, new JavaScriptExceptionThrownEventArgs(e.Message));
    }


    private void OnConsoleApiCalled(object? sender, ConsoleApiCalledEventArgs e)
    {
        if (this.JavaScriptConsoleApiCalled != null)
        {
            for (int i = 0; i < e.Arguments.Count; i++)
            {
                this.JavaScriptConsoleApiCalled(this, new JavaScriptConsoleApiCalledEventArgs
                (
                    messageContent: e.Arguments[i].Value,
                    messageTimeStamp: e.Timestamp,
                    messageType: e.Type
                ));
            }
        }
    }
}
