// <copyright file="W3CWireProtocolCommandInfoRepository.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;

#nullable enable

namespace OpenQA.Selenium.Remote
{
    /// <summary>
    /// Holds the information about all commands specified by the JSON wire protocol.
    /// This class cannot be inherited, as it is intended to be a singleton, and
    /// allowing subclasses introduces the possibility of multiple instances.
    /// </summary>
    public sealed class W3CWireProtocolCommandInfoRepository : CommandInfoRepository
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="W3CWireProtocolCommandInfoRepository"/> class.
        /// </summary>
        public W3CWireProtocolCommandInfoRepository()
            : base()
        {
            this.InitializeCommandDictionary();
        }

        /// <summary>
        /// Gets the level of the W3C WebDriver specification that this repository supports.
        /// </summary>
        public override int SpecificationLevel => 1;

        /// <summary>
        /// Gets the <see cref="Type"/> that is valid for this <see cref="CommandInfoRepository"/>
        /// </summary>
        protected override Type RepositoryCommandInfoType => typeof(HttpCommandInfo);

        /// <summary>
        /// Initializes the dictionary of commands for the CommandInfoRepository
        /// </summary>
        protected override void InitializeCommandDictionary()
        {
            this.TryAddCommand(DriverCommand.Status, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/status"));
            this.TryAddCommand(DriverCommand.NewSession, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session"));
            this.TryAddCommand(DriverCommand.Quit, new HttpCommandInfo(HttpCommandInfo.DeleteCommand, "/session/{sessionId}"));
            this.TryAddCommand(DriverCommand.GetTimeouts, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/timeouts"));
            this.TryAddCommand(DriverCommand.SetTimeouts, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/timeouts"));
            this.TryAddCommand(DriverCommand.Get, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/url"));
            this.TryAddCommand(DriverCommand.GetCurrentUrl, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/url"));
            this.TryAddCommand(DriverCommand.GoBack, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/back"));
            this.TryAddCommand(DriverCommand.GoForward, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/forward"));
            this.TryAddCommand(DriverCommand.Refresh, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/refresh"));
            this.TryAddCommand(DriverCommand.GetTitle, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/title"));
            this.TryAddCommand(DriverCommand.GetCurrentWindowHandle, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/window"));
            this.TryAddCommand(DriverCommand.Close, new HttpCommandInfo(HttpCommandInfo.DeleteCommand, "/session/{sessionId}/window"));
            this.TryAddCommand(DriverCommand.SwitchToWindow, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/window"));
            this.TryAddCommand(DriverCommand.GetWindowHandles, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/window/handles"));
            this.TryAddCommand(DriverCommand.NewWindow, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/window/new"));
            this.TryAddCommand(DriverCommand.SwitchToFrame, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/frame"));
            this.TryAddCommand(DriverCommand.SwitchToParentFrame, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/frame/parent"));

            this.TryAddCommand(DriverCommand.GetWindowRect, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/window/rect"));
            this.TryAddCommand(DriverCommand.SetWindowRect, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/window/rect"));

            this.TryAddCommand(DriverCommand.MaximizeWindow, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/window/maximize"));
            this.TryAddCommand(DriverCommand.MinimizeWindow, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/window/minimize"));
            this.TryAddCommand(DriverCommand.FullScreenWindow, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/window/fullscreen"));
            this.TryAddCommand(DriverCommand.GetActiveElement, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/active"));
            this.TryAddCommand(DriverCommand.GetElementShadowRoot, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/shadow"));
            this.TryAddCommand(DriverCommand.FindElement, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/element"));
            this.TryAddCommand(DriverCommand.FindElements, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/elements"));
            this.TryAddCommand(DriverCommand.FindChildElement, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/element/{id}/element"));
            this.TryAddCommand(DriverCommand.FindChildElements, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/element/{id}/elements"));
            this.TryAddCommand(DriverCommand.FindShadowChildElement, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/shadow/{id}/element"));
            this.TryAddCommand(DriverCommand.FindShadowChildElements, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/shadow/{id}/elements"));
            this.TryAddCommand(DriverCommand.IsElementSelected, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/selected"));
            this.TryAddCommand(DriverCommand.ClickElement, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/element/{id}/click"));
            this.TryAddCommand(DriverCommand.ClearElement, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/element/{id}/clear"));
            this.TryAddCommand(DriverCommand.SendKeysToElement, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/element/{id}/value"));
            this.TryAddCommand(DriverCommand.GetElementAttribute, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/attribute/{name}"));
            this.TryAddCommand(DriverCommand.GetElementProperty, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/property/{name}"));
            this.TryAddCommand(DriverCommand.GetElementValueOfCssProperty, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/css/{name}"));
            this.TryAddCommand(DriverCommand.GetComputedAccessibleLabel, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/computedlabel"));
            this.TryAddCommand(DriverCommand.GetComputedAccessibleRole, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/computedrole"));
            this.TryAddCommand(DriverCommand.GetElementText, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/text"));
            this.TryAddCommand(DriverCommand.GetElementTagName, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/name"));
            this.TryAddCommand(DriverCommand.GetElementRect, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/rect"));
            this.TryAddCommand(DriverCommand.IsElementEnabled, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/enabled"));
            this.TryAddCommand(DriverCommand.GetPageSource, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/source"));
            this.TryAddCommand(DriverCommand.ExecuteScript, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/execute/sync"));
            this.TryAddCommand(DriverCommand.ExecuteAsyncScript, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/execute/async"));
            this.TryAddCommand(DriverCommand.GetAllCookies, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/cookie"));
            this.TryAddCommand(DriverCommand.GetCookie, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/cookie/{name}"));
            this.TryAddCommand(DriverCommand.AddCookie, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/cookie"));
            this.TryAddCommand(DriverCommand.DeleteCookie, new HttpCommandInfo(HttpCommandInfo.DeleteCommand, "/session/{sessionId}/cookie/{name}"));
            this.TryAddCommand(DriverCommand.DeleteAllCookies, new HttpCommandInfo(HttpCommandInfo.DeleteCommand, "/session/{sessionId}/cookie"));
            this.TryAddCommand(DriverCommand.Actions, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/actions"));
            this.TryAddCommand(DriverCommand.CancelActions, new HttpCommandInfo(HttpCommandInfo.DeleteCommand, "/session/{sessionId}/actions"));
            this.TryAddCommand(DriverCommand.DismissAlert, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/alert/dismiss"));
            this.TryAddCommand(DriverCommand.AcceptAlert, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/alert/accept"));
            this.TryAddCommand(DriverCommand.GetAlertText, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/alert/text"));
            this.TryAddCommand(DriverCommand.SetAlertValue, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/alert/text"));
            this.TryAddCommand(DriverCommand.Screenshot, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/screenshot"));
            this.TryAddCommand(DriverCommand.ElementScreenshot, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/screenshot"));
            this.TryAddCommand(DriverCommand.Print, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/print"));
            this.TryAddCommand(DriverCommand.AddVirtualAuthenticator, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/webauthn/authenticator"));
            this.TryAddCommand(DriverCommand.RemoveVirtualAuthenticator, new HttpCommandInfo(HttpCommandInfo.DeleteCommand, "/session/{sessionId}/webauthn/authenticator/{authenticatorId}"));
            this.TryAddCommand(DriverCommand.AddCredential, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/webauthn/authenticator/{authenticatorId}/credential"));
            this.TryAddCommand(DriverCommand.GetCredentials, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/webauthn/authenticator/{authenticatorId}/credentials"));
            this.TryAddCommand(DriverCommand.RemoveCredential, new HttpCommandInfo(HttpCommandInfo.DeleteCommand, "/session/{sessionId}/webauthn/authenticator/{authenticatorId}/credentials/{credentialId}"));
            this.TryAddCommand(DriverCommand.RemoveAllCredentials, new HttpCommandInfo(HttpCommandInfo.DeleteCommand, "/session/{sessionId}/webauthn/authenticator/{authenticatorId}/credentials"));
            this.TryAddCommand(DriverCommand.SetUserVerified, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/webauthn/authenticator/{authenticatorId}/uv"));

            // Commands below here are not included in the W3C specification,
            // but are required for full fidelity of execution with Selenium's
            // local-end implementation of WebDriver.
            this.TryAddCommand(DriverCommand.IsElementDisplayed, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/displayed"));
            this.TryAddCommand(DriverCommand.ElementEquals, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/element/{id}/equals/{other}"));
            this.TryAddCommand(DriverCommand.GetLog, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/se/log"));
            this.TryAddCommand(DriverCommand.GetAvailableLogTypes, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/se/log/types"));
            this.TryAddCommand(DriverCommand.UploadFile, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/se/file"));
            this.TryAddCommand(DriverCommand.GetDownloadableFiles, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/se/files"));
            this.TryAddCommand(DriverCommand.DownloadFile, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/se/files"));
            this.TryAddCommand(DriverCommand.DeleteDownloadableFiles, new HttpCommandInfo(HttpCommandInfo.DeleteCommand, "/session/{sessionId}/se/files"));
        }
    }
}
