// <copyright file="NetworkManager.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 OpenQA.Selenium.DevTools;

namespace OpenQA.Selenium;

/// <summary>
/// Provides methods for monitoring, intercepting, and modifying network requests and responses.
/// </summary>
public class NetworkManager : INetwork
{
    private readonly Lazy<DevToolsSession> session;
    private readonly List<NetworkRequestHandler> requestHandlers = new List<NetworkRequestHandler>();
    private readonly List<NetworkResponseHandler> responseHandlers = new List<NetworkResponseHandler>();
    private readonly List<NetworkAuthenticationHandler> authenticationHandlers = new List<NetworkAuthenticationHandler>();

    /// <summary>
    /// Initializes a new instance of the <see cref="NetworkManager"/> class.
    /// </summary>
    /// <param name="driver">The <see cref="IWebDriver"/> instance on which the network should be monitored.</param>
    [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Warnings are added to StartMonitoring and StopMonitoring")]
    [UnconditionalSuppressMessage("Trimming", "IL3050", Justification = "Warnings are added to StartMonitoring and StopMonitoring")]
    public NetworkManager(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
        // StartMonitoring().
        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 browser sends a network request.
    /// </summary>
    public event EventHandler<NetworkRequestSentEventArgs>? NetworkRequestSent;

    /// <summary>
    /// Occurs when a browser receives a network response.
    /// </summary>
    public event EventHandler<NetworkResponseReceivedEventArgs>? NetworkResponseReceived;

    /// <summary>
    /// Asynchronously starts monitoring for network traffic.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    [RequiresUnreferencedCode("NetworkManager is currently implemented with CDP. When it is implemented with BiDi, AOT will be supported")]
    [RequiresDynamicCode("NetworkManager is currently implemented with CDP. When it is implemented with BiDi, AOT will be supported.")]
    public async Task StartMonitoring()
    {
        this.session.Value.Domains.Network.RequestPaused += OnRequestPaused;
        this.session.Value.Domains.Network.AuthRequired += OnAuthRequired;
        this.session.Value.Domains.Network.ResponsePaused += OnResponsePaused;
        await this.session.Value.Domains.Network.EnableFetchForAllPatterns().ConfigureAwait(false);
        await this.session.Value.Domains.Network.EnableNetwork().ConfigureAwait(false);
        await this.session.Value.Domains.Network.DisableNetworkCaching().ConfigureAwait(false);
    }

    /// <summary>
    /// Asynchronously stops monitoring for network traffic.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    [RequiresUnreferencedCode("Network monitoring is currently implemented with CDP. When it is implemented with BiDi, AOT will be supported")]
    [RequiresDynamicCode("Network monitoring is currently implemented with CDP. When it is implemented with BiDi, AOT will be supported.")]
    public async Task StopMonitoring()
    {
        this.session.Value.Domains.Network.ResponsePaused -= OnResponsePaused;
        this.session.Value.Domains.Network.AuthRequired -= OnAuthRequired;
        this.session.Value.Domains.Network.RequestPaused -= OnRequestPaused;
        await this.session.Value.Domains.Network.EnableNetworkCaching().ConfigureAwait(false);
        await this.session.Value.Domains.Network.DisableNetwork().ConfigureAwait(false);
        await this.session.Value.Domains.Network.DisableFetch().ConfigureAwait(false);
    }

    /// <summary>
    /// Adds a <see cref="NetworkRequestHandler"/> to examine incoming network requests,
    /// and optionally modify the request or provide a response.
    /// </summary>
    /// <param name="handler">The <see cref="NetworkRequestHandler"/> to add.</param>
    /// <exception cref="ArgumentNullException">If <paramref name="handler"/> is <see langword="null"/>.</exception>
    public void AddRequestHandler(NetworkRequestHandler handler)
    {
        if (handler == null)
        {
            throw new ArgumentNullException(nameof(handler), "Request handler cannot be null");
        }

        if (handler.RequestMatcher == null)
        {
            throw new ArgumentException("Matcher for request cannot be null", nameof(handler));
        }

        if (handler.RequestTransformer == null && handler.ResponseSupplier == null)
        {
            throw new ArgumentException("Request transformer and response supplier cannot both be null", nameof(handler));
        }

        this.requestHandlers.Add(handler);
    }

    /// <summary>
    /// Clears all added <see cref="NetworkRequestHandler"/> instances.
    /// </summary>
    public void ClearRequestHandlers()
    {
        this.requestHandlers.Clear();
    }

    /// <summary>
    /// Adds a <see cref="NetworkAuthenticationHandler"/> to supply authentication
    /// credentials for network requests.
    /// </summary>
    /// <param name="handler">The <see cref="NetworkAuthenticationHandler"/> to add.</param>
    public void AddAuthenticationHandler(NetworkAuthenticationHandler handler)
    {
        if (handler == null)
        {
            throw new ArgumentNullException(nameof(handler), "Authentication handler cannot be null");
        }

        if (handler.UriMatcher == null)
        {
            throw new ArgumentException("Matcher for delegate for URL cannot be null", nameof(handler));
        }

        if (handler.Credentials == null)
        {
            throw new ArgumentException("Credentials to use for authentication cannot be null", nameof(handler));
        }

        if (handler.Credentials is not PasswordCredentials)
        {
            throw new ArgumentException("Credentials must contain user name and password (PasswordCredentials)", nameof(handler));
        }

        this.authenticationHandlers.Add(handler);
    }

    /// <summary>
    /// Clears all added <see cref="NetworkAuthenticationHandler"/> instances.
    /// </summary>
    public void ClearAuthenticationHandlers()
    {
        this.authenticationHandlers.Clear();
    }

    /// <summary>
    /// Adds a <see cref="NetworkResponseHandler"/> to examine received network responses,
    /// and optionally modify the response.
    /// </summary>
    /// <param name="handler">The <see cref="NetworkResponseHandler"/> to add.</param>
    public void AddResponseHandler(NetworkResponseHandler handler)
    {
        if (handler == null)
        {
            throw new ArgumentNullException(nameof(handler), "Request handler cannot be null");
        }

        if (handler.ResponseMatcher == null)
        {
            throw new ArgumentException("Matcher for response cannot be null", nameof(handler));
        }

        this.responseHandlers.Add(handler);
    }

    /// <summary>
    /// Clears all added <see cref="NetworkResponseHandler"/> instances.
    /// </summary>
    public void ClearResponseHandlers()
    {
        this.responseHandlers.Clear();
    }

    private async Task OnAuthRequired(object sender, AuthRequiredEventArgs e)
    {
        string requestId = e.RequestId;
        Uri uri = new Uri(e.Uri);
        bool successfullyAuthenticated = false;
        foreach (var authenticationHandler in this.authenticationHandlers)
        {
            if (authenticationHandler.UriMatcher!.Invoke(uri))
            {
                PasswordCredentials credentials = (PasswordCredentials)authenticationHandler.Credentials!;
                await this.session.Value.Domains.Network.ContinueWithAuth(e.RequestId, credentials.UserName, credentials.Password).ConfigureAwait(false);
                successfullyAuthenticated = true;
                break;
            }
        }

        if (!successfullyAuthenticated)
        {
            await this.session.Value.Domains.Network.CancelAuth(e.RequestId).ConfigureAwait(false);
        }
    }

    private async Task OnRequestPaused(object sender, RequestPausedEventArgs e)
    {
        this.NetworkRequestSent?.Invoke(this, new NetworkRequestSentEventArgs(e.RequestData));

        foreach (var handler in this.requestHandlers)
        {
            if (handler.RequestMatcher!.Invoke(e.RequestData))
            {
                if (handler.RequestTransformer != null)
                {
                    await this.session.Value.Domains.Network.ContinueRequest(handler.RequestTransformer(e.RequestData)).ConfigureAwait(false);
                    return;
                }

                if (handler.ResponseSupplier != null)
                {
                    await this.session.Value.Domains.Network.ContinueRequestWithResponse(e.RequestData, handler.ResponseSupplier(e.RequestData)).ConfigureAwait(false);
                    return;
                }
            }
        }

        await this.session.Value.Domains.Network.ContinueRequestWithoutModification(e.RequestData).ConfigureAwait(false);
    }

    private async Task OnResponsePaused(object sender, ResponsePausedEventArgs e)
    {
        if (e.ResponseData.Headers.Count > 0)
        {
            // If no headers are present, the body cannot be retrieved.
            await this.session.Value.Domains.Network.AddResponseBody(e.ResponseData).ConfigureAwait(false);
        }

        this.NetworkResponseReceived?.Invoke(this, new NetworkResponseReceivedEventArgs(e.ResponseData));

        foreach (var handler in this.responseHandlers)
        {
            if (handler.ResponseMatcher!.Invoke(e.ResponseData))
            {
                // NOTE: We create a dummy HttpRequestData object here, because the ContinueRequestWithResponse
                // method demands one; however, the only property used by that method is the RequestId property.
                // It might be better to refactor that method signature to simply pass the request ID, or
                // alternatively, just pass the response data, which should also contain the request ID anyway.
                HttpRequestData requestData = new HttpRequestData { RequestId = e.ResponseData.RequestId };
                await this.session.Value.Domains.Network.ContinueRequestWithResponse(requestData, handler.ResponseTransformer!(e.ResponseData)).ConfigureAwait(false);
                return;
            }
        }

        await this.session.Value.Domains.Network.ContinueResponseWithoutModification(e.ResponseData).ConfigureAwait(false);
    }
}
