// <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 OpenQA.Selenium.DevTools;
using OpenQA.Selenium.Internal;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;

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, 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(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
                ));
            }
        }
    }
}
