// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed 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.

import 'dart:convert' show base64;
import 'dart:typed_data';

import '../../async_core.dart' as async_core;
import '../common/by.dart';
import '../common/request.dart';
import '../common/request_client.dart';
import '../common/spec.dart';
import '../common/utils.dart';
import '../common/webdriver_handler.dart';
import 'common.dart';
import 'common_stub.dart' if (dart.library.io) 'common_io.dart';
import 'cookies.dart';
import 'keyboard.dart';
import 'logs.dart';
import 'mouse.dart';
import 'target_locator.dart';
import 'timeouts.dart';
import 'web_element.dart';
import 'window.dart';

/// Interacts with WebDriver.
class WebDriver implements SearchContext {
  final SyncRequestClient _client;

  final WebDriverHandler _handler;

  final Map<String, dynamic> capabilities;

  final WebDriverSpec spec;

  final String id;

  final Uri uri;

  WebDriver(this.uri, this.id, this.capabilities, this._client, this.spec)
      : _handler = getHandler(spec);

  /// Produces a [async_core.WebDriver] with the same session ID. Allows
  /// backwards compatibility with other frameworks.
  async_core.WebDriver get asyncDriver => createAsyncWebDriver(this);

  @override
  async_core.SearchContext get asyncContext => asyncDriver;

  /// Preferred method for registering listeners. Listeners are expected to
  /// return a Future. Use new Future.value() for synchronous listeners.
  void addEventListener(SyncWebDriverListener listener) {
    _client.addEventListener(listener);
  }

  /// The current url.
  String get currentUrl => _client.send(_handler.core.buildCurrentUrlRequest(),
      _handler.core.parseCurrentUrlResponse);

  /// Navigates to the specified url
  void get(Object /* Uri | String */ url) {
    _client.send(
        _handler.navigation.buildNavigateToRequest(
          (url is Uri) ? url.toString() : url as String,
        ),
        _handler.navigation.parseNavigateToResponse);
  }

  ///  Navigates forwards in the browser history, if possible.
  void forward() {
    _client.send(_handler.navigation.buildForwardRequest(),
        _handler.navigation.parseForwardResponse);
  }

  /// Navigates backwards in the browser history, if possible.
  void back() {
    _client.send(_handler.navigation.buildBackRequest(),
        _handler.navigation.parseBackResponse);
  }

  /// Refreshes the current page.
  void refresh() {
    _client.send(_handler.navigation.buildRefreshRequest(),
        _handler.navigation.parseRefreshResponse);
  }

  /// The title of the current page.
  String get title => _client.send(
      _handler.core.buildTitleRequest(), _handler.core.parseTitleResponse);

  /// Search for multiple elements within the entire current page.
  @override
  List<WebElement> findElements(By by) {
    final ids = _client.send(
        _handler.elementFinder.buildFindElementsRequest(by),
        _handler.elementFinder.parseFindElementsResponse);

    final elements = <WebElement>[];
    var i = 0;
    for (final id in ids) {
      elements.add(WebElement(this, _client, _handler, id, this, by, i++));
    }

    return elements;
  }

  /// Search for an element within the entire current page.
  ///
  /// Throws [async_core.NoSuchElementException] if a matching element is not
  /// found.
  @override
  WebElement findElement(By by) => WebElement(
      this,
      _client,
      _handler,
      _client.send(_handler.elementFinder.buildFindElementRequest(by),
          _handler.elementFinder.parseFindElementResponse),
      this,
      by);

  /// Search for an element by xpath within the entire current page.
  /// Throws [async_core.NoSuchElementException] if a matching element is not
  /// found.
  WebElement findElementByXpath(String by) => findElement(By.xpath(by));

  /// An artist's rendition of the current page's source.
  String get pageSource => _client.send(_handler.core.buildPageSourceRequest(),
      _handler.core.parsePageSourceResponse);

  /// Quits the browser.
  void quit({bool closeSession = true}) {
    if (closeSession) {
      _client.send(_handler.core.buildDeleteSessionRequest(),
          _handler.core.parseDeleteSessionResponse);
    }
  }

  /// Closes the current window.
  ///
  /// This is rather confusing and will be removed.
  /// Should replace all usages with [window.close()] or [quit()].
  @Deprecated('Use `window.close()` or `quit()` instead.')
  void close() {
    window.close();
  }

  /// Handles for all of the currently displayed tabs/windows.
  List<Window> get windows => _client.send(
      _handler.window.buildGetWindowsRequest(),
      (response) => _handler.window
          .parseGetWindowsResponse(response)
          .map<Window>((w) => Window(_client, _handler, w))
          .toList());

  /// Handle for the active tab/window.
  Window get window => _client.send(
      _handler.window.buildGetActiveWindowRequest(),
      (response) => Window(_client, _handler,
          _handler.window.parseGetActiveWindowResponse(response)));

  /// The currently focused element, or the body element if no element has
  /// focus.
  WebElement? get activeElement {
    final id = _client.send(
        _handler.elementFinder.buildFindActiveElementRequest(),
        _handler.elementFinder.parseFindActiveElementResponse);
    if (id != null) {
      return WebElement(this, _client, _handler, id, this, 'activeElement');
    }
    return null;
  }

  /// Changes focus to specified targets.
  ///
  /// Available targets are window, frame, and the current alert.
  TargetLocator get switchTo => TargetLocator(this, _client, _handler);

  Cookies get cookies => Cookies(_client, _handler);

  /// [logs.get(logType)] will give list of logs captured in browser.
  ///
  /// Note that for W3C/Firefox, this is not supported and will produce empty
  /// list of logs, as the spec for this in W3C is not agreed on and Firefox
  /// refuses to support non-spec features. See
  /// https://github.com/w3c/webdriver/issues/406.
  Logs get logs => Logs(_client, _handler);

  Timeouts get timeouts => Timeouts(_client, _handler);

  Keyboard get keyboard => Keyboard(_client, _handler);

  Mouse get mouse => Mouse(_client, _handler);

  /// Take a screenshot of the current page as PNG and return it as
  /// base64-encoded string.
  String captureScreenshotAsBase64() => _client.send(
      _handler.core.buildScreenshotRequest(),
      _handler.core.parseScreenshotResponse);

  /// Take a screenshot of the specified element as PNG and return it as
  /// base64-encoded string.
  String captureElementScreenshotAsBase64(WebElement element) => _client.send(
      _handler.core.buildElementScreenshotRequest(element.id),
      _handler.core.parseScreenshotResponse);

  /// Take a screenshot of the current page as PNG as list of uint8.
  Uint8List captureScreenshotAsList() {
    final base64Encoded = captureScreenshotAsBase64();
    return base64.decode(base64Encoded);
  }

  /// Take a screenshot of the specified element as PNG as list of uint8.
  Uint8List captureElementScreenshotAsList(WebElement element) {
    final base64Encoded = captureElementScreenshotAsBase64(element);
    return base64.decode(base64Encoded);
  }

  /// Inject a snippet of JavaScript into the page for execution in the context
  /// of the currently selected frame. The executed script is assumed to be
  /// asynchronous and must signal that is done by invoking the provided
  /// callback, which is always provided as the final argument to the function.
  /// The value to this callback will be returned to the client.
  ///
  /// Asynchronous script commands may not span page loads. If an unload event
  /// is fired while waiting for a script result, an error will be thrown.
  ///
  /// The script argument defines the script to execute in the form of a
  /// function body. The function will be invoked with the provided args array
  /// and the values may be accessed via the arguments object in the order
  /// specified. The final argument will always be a callback function that must
  /// be invoked to signal that the script has finished.
  ///
  /// Arguments may be any JSON-able object. WebElements will be converted to
  /// the corresponding DOM element. Likewise, any DOM Elements in the script
  /// result will be converted to WebElements.
  dynamic executeAsync(String script, List args) => _client.send(
      _handler.core.buildExecuteAsyncRequest(script, args),
      (response) => _handler.core.parseExecuteAsyncResponse(
          response,
          (elementId) => WebElement(
              this, _client, _handler, elementId, this, 'javascript')));

  /// Inject a snippet of JavaScript into the page for execution in the context
  /// of the currently selected frame. The executed script is assumed to be
  /// synchronous and the result of evaluating the script is returned.
  ///
  /// The script argument defines the script to execute in the form of a
  /// function body. The value returned by that function will be returned to the
  /// client. The function will be invoked with the provided args array and the
  /// values may be accessed via the arguments object in the order specified.
  ///
  /// Arguments may be any JSON-able object. WebElements will be converted to
  /// the corresponding DOM element. Likewise, any DOM Elements in the script
  /// result will be converted to WebElements.
  dynamic execute(String script, List args) => _client.send(
      _handler.core.buildExecuteRequest(script, args),
      (response) => _handler.core.parseExecuteResponse(
          response,
          (elementId) => WebElement(
              this, _client, _handler, elementId, this, 'javascript')));

  /// Performs post request on command to the WebDriver server.
  ///
  /// For use by supporting WebDriver packages.
  dynamic postRequest(String command, [Object? params]) => _client.send(
      _handler.buildGeneralRequest(HttpMethod.httpPost, command, params),
      (response) => _handler.parseGeneralResponse(
          response, (elementId) => getElement(elementId, this)));

  /// Performs get request on command to the WebDriver server.
  ///
  /// For use by supporting WebDriver packages.
  dynamic getRequest(String command) => _client.send(
      _handler.buildGeneralRequest(HttpMethod.httpGet, command),
      (response) => _handler.parseGeneralResponse(
          response, (elementId) => getElement(elementId, this)));

  /// Performs delete request on command to the WebDriver server.
  ///
  /// For use by supporting WebDriver packages.
  dynamic deleteRequest(String command) => _client.send(
        _handler.buildGeneralRequest(HttpMethod.httpDelete, command),
        (response) => _handler.parseGeneralResponse(
          response,
          (elementId) => getElement(elementId, this),
        ),
      );

  WebElement getElement(
    String elementId, [
    SearchContext? context,
    Object? locator,
    int? index,
  ]) =>
      WebElement(
        this,
        _client,
        _handler,
        elementId,
        context,
        locator,
        index,
      );

  @override
  WebDriver get driver => this;

  @override
  String toString() => '$_handler.webdriver($_client)';
}
