// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library webdriver;

import 'dart:json' as json;
import 'dart:uri';
import 'dart:io';

part 'src/base64decoder.dart';

/**
 * WebDriver bindings for Dart.
 *
 * These bindings are based on the WebDriver JSON wire protocol spec
 * (http://code.google.com/p/selenium/wiki/JsonWireProtocol). Not
 * all of these commands are implemented yet by WebDriver itself.
 * Nontheless this is a complete implementation of the spec as the
 * unsupported commands may be supported in the future. Currently,
 * there are known issues with local and session storage, script
 * execution, and log access.
 *
 * To use these bindings, the Selenium standalone server must be running.
 * You can download it at http://code.google.com/p/selenium/downloads/list.
 *
 * There are a number of commands that use ids to access page elements.
 * These ids are not the HTML ids; they are opaque ids internal to
 * WebDriver. To get the id for an element you would first need to do
 * a search, get the results, and extract the WebDriver id from the returned
 * [Map] using the 'ELEMENT' key. For example:
 *
 *     String id;
 *     WebDriverSession session;
 *     Future f = web_driver.newSession('chrome');
 *     f.chain((_session) {
 *       session = _session;
 *       return session.setUrl('http://my.web.site.com');
 *    }).chain((_) {
 *      return session.findElement('id', 'username');
 *    }).chain((element) {
 *      id = element['ELEMENT'];
 *      return session.sendKeyStrokesToElement(id,
 *          [ 'j', 'o', 'e', ' ', 'u', 's', 'e', 'r' ]);
 *    }).chain((_) {
 *      return session.submit(id);
 *    }).chain((_) {
 *      return session.close();
 *    }).then((_) {
 *      session = null;
 *    });
 */

void writeStringToFile(String fileName, String contents) {
  new File(fileName).writeAsStringSync(contents);
}

void writeBytesToFile(String fileName, List<int> contents) {
  new File(fileName).writeAsBytesSync(contents);
}

class WebDriverError {
  static List _errorTypes = null;
  static List _errorDetails = null;
  int statusCode;
  String type;
  String message;
  String details;
  String results;

  WebDriverError(this.statusCode, this.message, [this.results = '']) {
    /** These correspond to WebDrive exception types. */
    if (_errorTypes == null) {
      _errorTypes = [
        null,
        'IndexOutOfBounds',
        'NoCollection',
        'NoString',
        'NoStringLength',
        'NoStringWrapper',
        'NoSuchDriver',
        'NoSuchElement',
        'NoSuchFrame',
        'UnknownCommand',
        'ObsoleteElement',
        'ElementNotDisplayed',
        'InvalidElementState',
        'Unhandled',
        'Expected',
        'ElementNotSelectable',
        'NoSuchDocument',
        'UnexpectedJavascript',
        'NoScriptResult',
        'XPathLookup',
        'NoSuchCollection',
        'TimeOut',
        'NullPointer',
        'NoSuchWindow',
        'InvalidCookieDomain',
        'UnableToSetCookie',
        'UnexpectedAlertOpen',
        'NoAlertOpen',
        'ScriptTimeout',
        'InvalidElementCoordinates',
        'IMENotAvailable',
        'IMEEngineActivationFailed',
        'InvalidSelector',
        'SessionNotCreatedException',
        'MoveTargetOutOfBounds'
      ];
      // Explanations of the eror types. In thoses cases where the
      // explanation is the same as the type (e.g. NoCollection), that is an
      // error type used by an old version of the IE driver and is deprecated.
      _errorDetails = [
        null,
        'IndexOutOfBounds',
        'NoCollection',
        'NoString',
        'NoStringLength',
        'NoStringWrapper',
        'NoSuchDriver',
        'An element could not be located on the page using the given '
            'search parameters.',
        'A request to switch to a frame could not be satisfied because the '
            'frame could not be found.',
        'The requested resource could not be found, or a request was '
            'received using an HTTP method that is not supported by the '
            'mapped resource.',
        'An element command failed because the referenced element is no '
            'longer attached to the DOM.',
        'An element command could not be completed because the element '
            'is not visible on the page.',
        'An element command could not be completed because the element is in '
            'an invalid state (e.g. attempting to click a disabled element).',
        'An unknown server-side error occurred while processing the command.',
        'Expected',
        'An attempt was made to select an element that cannot be selected.',
        'NoSuchDocument',
        'An error occurred while executing user supplied JavaScript.',
        'NoScriptResult',
        'An error occurred while searching for an element by XPath.',
        'NoSuchCollection',
        'An operation did not complete before its timeout expired.',
        'NullPointer',
        'A request to switch to a different window could not be satisfied '
            'because the window could not be found.',
        'An illegal attempt was made to set a cookie under a different '
            'domain than the current page.',
        'A request to set a cookie\'s value could not be satisfied.',
        'A modal dialog was open, blocking this operation.',
        'An attempt was made to operate on a modal dialog when one was '
            'not open.',
        'A script did not complete before its timeout expired.',
        'The coordinates provided to an interactions operation are invalid.',
        'IME was not available.',
        'An IME engine could not be started.',
        'Argument was an invalid selector (e.g. XPath/CSS).',
        'A new session could not be created.',
        'Target provided for a move action is out of bounds.'
      ];
    }
    if (statusCode < 0 || statusCode > 32) {
      type = 'External';
      details = '';
    } else {
      type = _errorTypes[statusCode];
      details = _errorDetails[statusCode];
    }
  }

  String toString() {
    return '$statusCode $type: $message $results\n$details';
  }
}

/**
 * Base class for all WebDriver request classes. This class wraps up
 * an URL prefix (host, port, and initial path), and provides a client
 * function for doing HTTP requests with JSON payloads.
 */
class WebDriverBase {

  String _host;
  int _port;
  String _path;
  String _url;

  String get path => _path;
  String get url => _url;

  /**
   * The default URL for WebDriver remote server is
   * http://localhost:4444/wd/hub.
   */
  WebDriverBase.fromUrl([this._url = 'http://localhost:4444/wd/hub']) {
    // Break out the URL components.
    var re = new RegExp('[^:/]+://([^/]+)(/.*)');
    var matches = re.firstMatch(_url);
    _host = matches[1];
    _path = matches[2];
    var idx = _host.indexOf(':');
    if (idx >= 0) {
      _port = int.parse(_host.substring(idx+1));
      _host = _host.substring(0, idx);
    } else {
      _port = 80;
    }
  }

  WebDriverBase([
      this._host = 'localhost',
      this._port = 4444,
      this._path = '/wd/hub']) {
    _url = 'http://$_host:$_port$_path';
  }

  /**
   * Execute a request to the WebDriver server. [http_method] should be
   * one of 'GET', 'POST', or 'DELETE'. [command] is the text to append
   * to the base URL path to get the full URL. [params] are the additional
   * parameters. If a [List] or [Map] they will be posted as JSON parameters.
   * If a number or string, "/params" is appended to the URL.
   */
  void _serverRequest(String http_method, String command, Completer completer,
                      [List successCodes, Map params, Function customHandler]) {
    var status = 0;
    var results = null;
    var message = null;
    if (successCodes == null) {
      successCodes = [ 200, 204 ];
    }
    try {
      if (params != null && params is List && http_method != 'POST') {
        throw new Exception(
          'The http method called for ${command} is ${http_method} but it has '
          'to be POST if you want to pass the JSON params '
          '${json.stringify(params)}');
      }

      var path = command;
      if (params != null && (params is num || params is String)) {
        path = '$path/$params';
      }

      var client = new HttpClient();
      var connection = client.open(http_method, _host, _port, path);

      connection.onRequest = (r) {
        r.headers.add(HttpHeaders.ACCEPT, "application/json");
        r.headers.add(
            HttpHeaders.CONTENT_TYPE, 'application/json;charset=UTF-8');
        OutputStream s = r.outputStream;
        if (params != null && params is Map) {
          s.writeString(json.stringify(params));
        }
        s.close();
      };
      connection.onError = (e) {
        if (completer != null) {
          completer.completeError(new WebDriverError(-1, e));
          completer = null;
        }
      };
      connection.followRedirects = false;
      connection.onResponse = (r) {
        StringInputStream s = new StringInputStream(r.inputStream);
        StringBuffer sbuf = new StringBuffer();
        s.onData = () {
          var data = s.read();
          if (data != null) {
            sbuf.add(data);
          }
        };
        s.onClosed = () {
          var value = null;
          results  = sbuf.toString().trim();
          // For some reason we get a bunch of NULs on the end
          // of the text and the json.parse blows up on these, so
          // strip them. We have to do this the hard way as
          // replaceAll('\0', '') does not work.
          // These NULs can be seen in the TCP packet, so it is not
          // an issue with character encoding; it seems to be a bug
          // in WebDriver stack.
          for (var i = results.length; --i >= 0;) {
            var code = results.charCodeAt(i);
            if (code != 0) {
              results = results.substring(0, i+1);
              break;
            }
          }
          if (successCodes.indexOf(r.statusCode) < 0) {
            throw 'Unexpected response ${r.statusCode}';
          }
          if (status == 0 && results.length > 0) {
            // 4xx responses send plain text; others send JSON.
            if (r.statusCode < 400) {
              results = json.parse(results);
              status = results['status'];
            }
            if (results is Map && (results as Map).containsKey('value')) {
              value = results['value'];
            }
            if (value is Map && value.containsKey('message')) {
              message = value['message'];
            }
          }
          if (status == 0) {
            if (customHandler != null) {
              customHandler(r, value);
            } else if (completer != null) {
              completer.complete(value);
            }
          }
        };
      };
    } catch (e, s) {
      completer.completeError(
          new WebDriverError(-1, e), s);
      completer = null;
    }
  }

  Future _simpleCommand(method, extraPath, [successCodes, params]) {
    var completer = new Completer();
    _serverRequest(method, '${_path}/$extraPath', completer,
          successCodes, params: params);
    return completer.future;
  }

  Future _get(extraPath, [successCodes]) =>
      _simpleCommand('GET', extraPath, successCodes);

  Future _post(extraPath, [successCodes, params]) =>
      _simpleCommand('POST', extraPath, successCodes, params);

  Future _delete(extraPath, [successCodes]) =>
      _simpleCommand('DELETE', extraPath, successCodes);
}

class WebDriver extends WebDriverBase {

  WebDriver(host, port, path) : super(host, port, path);

  /**
   * Create a new session. The server will attempt to create a session that
   * most closely matches the desired and required capabilities. Required
   * capabilities have higher priority than desired capabilities and must be
   * set for the session to be created.
   *
   * The capabilities are:
   *
   * - browserName (String)  The name of the browser being used; should be one
   *   of chrome|firefox|htmlunit|internet explorer|iphone.
   *
   * - version (String) The browser version, or the empty string if unknown.
   *
   * - platform (String) A key specifying which platform the browser is
   *   running on. This value should be one of WINDOWS|XP|VISTA|MAC|LINUX|UNIX.
   *   When requesting a new session, the client may specify ANY to indicate
   *   any available platform may be used.
   *
   * - javascriptEnabled (bool) Whether the session supports executing user
   *   supplied JavaScript in the context of the current page.
   *
   * - takesScreenshot (bool) Whether the session supports taking screenshots
   *   of the current page.
   *
   * - handlesAlerts (bool) Whether the session can interact with modal popups,
   *   such as window.alert and window.confirm.
   *
   * - databaseEnabled (bool) Whether the session can interact database storage.
   *
   * - locationContextEnabled (bool) Whether the session can set and query the
   *   browser's location context.
   *
   * - applicationCacheEnabled (bool) Whether the session can interact with
   *   the application cache.
   *
   * - browserConnectionEnabled (bool) Whether the session can query for the
   *   browser's connectivity and disable it if desired.
   *
   * - cssSelectorsEnabled (bool) Whether the session supports CSS selectors
   *   when searching for elements.
   *
   * - webStorageEnabled (bool) Whether the session supports interactions with
   *   storage objects.
   *
   * - rotatable (bool) Whether the session can rotate the current page's
   *   current layout between portrait and landscape orientations (only applies
   *   to mobile platforms).
   *
   * - acceptSslCerts (bool) Whether the session should accept all SSL certs
   *   by default.
   *
   * - nativeEvents (bool) Whether the session is capable of generating native
   *   events when simulating user input.
   *
   * - proxy (proxy object) Details of any proxy to use. If no proxy is
   *   specified, whatever the system's current or default state is used.
   *
   * The format of the proxy object is:
   *
   * - proxyType (String) The type of proxy being used. Possible values are:
   *
   *   direct - A direct connection - no proxy in use,
   *
   *   manual - Manual proxy settings configured,
   *
   *   pac - Proxy autoconfiguration from a URL),
   *
   *   autodetect (proxy autodetection, probably with WPAD),
   *
   *   system - Use system settings
   *
   * - proxyAutoconfigUrl (String) Required if proxyType == pac, Ignored
   *   otherwise. Specifies the URL to be used for proxy autoconfiguration.
   *
   * - ftpProxy, httpProxy, sslProxy (String) (Optional, Ignored if
   *   proxyType != manual) Specifies the proxies to be used for FTP, HTTP
   *   and HTTPS requests respectively. Behaviour is undefined if a request
   *   is made, where the proxy for the particular protocol is undefined,
   *   if proxyType is manual.
   *
   * Potential Errors: SessionNotCreatedException (if a required capability
   * could not be set).
   */
  Future<WebDriverSession> newSession([
      browser = 'chrome', Map additional_capabilities]) {
    var completer = new Completer();
    if (additional_capabilities == null) {
      additional_capabilities = {};
    }

    additional_capabilities['browserName'] = browser;

    _serverRequest('POST', '${_path}/session', null, [ 302 ],
        customHandler: (r, v) {
          var url = r.headers.value(HttpHeaders.LOCATION);
          var session = new WebDriverSession.fromUrl(url);
          completer.complete(session);
        }, params: { 'desiredCapabilities': additional_capabilities });
    return completer.future;
  }

  /** Get the set of currently active sessions. */
  Future<List<WebDriverSession>> getSessions() {
    var completer = new Completer();
    _get('sessions', (result) {
      var _sessions = [];
      for (var session in result) {
        _sessions.add(new WebDriverSession.fromUrl(
          '${this._path}/session/${session["id"]}'));
      }
      completer.complete(_sessions);
    });
    return completer.future;
  }

  /** Query the server's current status. */
  Future<Map> getStatus() => _get('status');
}

class WebDriverWindow extends WebDriverBase {
  WebDriverWindow.fromUrl(url) : super.fromUrl(url);

  /** Get the window size. */
  Future<Map> getSize() => _get('size');

  /**
   * Set the window size.
   *
   * Potential Errors:
   *   NoSuchWindow - If the specified window cannot be found.
   */
  Future<String> setSize(int width, int height) =>
      _post('size', params: { 'width': width, 'height': height });

  /** Get the window position. */
  Future<Map> getPosition() => _get('position');

  /**
   * Set the window position.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future setPosition(int x, int y) =>
      _post('position', params: { 'x': x, 'y': y });

  /** Maximize the specified window if not already maximized. */
  Future maximize() => _post('maximize');
}

class WebDriverSession extends WebDriverBase {
  WebDriverSession.fromUrl(url) : super.fromUrl(url);

  /** Close the session. */
  Future close() => _delete('');

  /** Get the session capabilities. See [newSession] for details. */
  Future<Map> getCapabilities() => _get('');

  /**
   * Configure the amount of time in milliseconds that a script can execute
   * for before it is aborted and a Timeout error is returned to the client.
   */
  Future setScriptTimeout(t) =>
      _post('timeouts', params: { 'type': 'script', 'ms': t });

  /*Future<String> setImplicitWaitTimeout(t) =>
      simplePost('timeouts', { 'type': 'implicit', 'ms': t });*/

  /**
   * Configure the amount of time in milliseconds that a page can load for
   * before it is aborted and a Timeout error is returned to the client.
   */
  Future setPageLoadTimeout(t) =>
      _post('timeouts', params: { 'type': 'page load', 'ms': t });

  /**
   * Set the amount of time, in milliseconds, that asynchronous scripts
   * executed by /session/:sessionId/execute_async are permitted to run
   * before they are aborted and a Timeout error is returned to the client.
   */
  Future setAsyncScriptTimeout(t) =>
      _post('timeouts/async_script', params: { 'ms': t });

  /**
   * Set the amount of time the driver should wait when searching for elements.
   * When searching for a single element, the driver should poll the page until
   * an element is found or the timeout expires, whichever occurs first. When
   * searching for multiple elements, the driver should poll the page until at
   * least one element is found or the timeout expires, at which point it should
   * return an empty list.
   *
   * If this command is never sent, the driver should default to an implicit
   * wait of 0ms.
   */
  Future setImplicitWaitTimeout(t) =>
      _post('timeouts/implicit_wait', params: { 'ms': t });

  /**
   * Retrieve the current window handle.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<String> getWindowHandle() => _get('window_handle');

  /**
   * Retrieve a [WebDriverWindow] for the specified window. We don't
   * have to use a Future here but do so to be consistent.
   */
  Future<WebDriverWindow> getWindow([handle = 'current']) {
    var completer = new Completer();
    completer.complete(new WebDriverWindow.fromUrl('${_url}/window/$handle'));
    return completer.future;
  }

  /** Retrieve the list of all window handles available to the session. */
  Future<List<String>> getWindowHandles() => _get('window_handles');

  /**
   * Retrieve the URL of the current page.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<String> getUrl() => _get('url');

  /**
   * Navigate to a new URL.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future setUrl(String url) => _post('url', params: { 'url': url });

  /**
   * Navigate forwards in the browser history, if possible.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future navigateForward() => _post('forward');

  /**
   * Navigate backwards in the browser history, if possible.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future navigateBack() => _post('back');

  /**
   * Refresh the current page.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future refresh() => _post('refresh');

  /**
   * 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 to the
   * client.
   *
   * 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-primitive, array, or JSON object. JSON objects
   * that define a WebElement reference will be converted to the corresponding
   * DOM element. Likewise, any WebElements in the script result will be
   * returned to the client as WebElement JSON objects.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference, JavaScriptError.
   */
  Future execute(String script, [List args]) =>
      _post('execute', params: { 'script': script, 'args': args });

  /**
   * 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 it 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 should be returned
   * to the client.
   *
   * 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-primitive, array, or JSON object. JSON objects
   * that define a WebElement reference will be converted to the corresponding
   * DOM element. Likewise, any WebElements in the script result will be
   * returned to the client as WebElement JSON objects.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference, Timeout (controlled
   * by the [setAsyncScriptTimeout] command), JavaScriptError (if the script
   * callback is not invoked before the timout expires).
   */
  Future executeAsync(String script, [List args]) =>
      _post('execute_async', params: { 'script': script, 'args': args });

  /**
   * Take a screenshot of the current page (PNG).
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<List<int>> getScreenshot([fname]) {
    var completer = new Completer();
    var result = _serverRequest('GET', '$_path/screenshot', completer,
        customHandler: (r, v) {
      var image = Base64Decoder.decode(v);
      if (fname != null) {
        writeBytesToFile(fname, image);
      }
      completer.complete(image);
    });
    return completer.future;
  }

  /**
   * List all available IME (Input Method Editor) engines on the machine.
   * To use an engine, it has to be present in this list.
   *
   * Potential Errors: ImeNotAvailableException.
   */
  Future<List<String>> getAvailableImeEngines() =>
      _get('ime/available_engines');

  /**
   * Get the name of the active IME engine. The name string is
   * platform specific.
   *
   * Potential Errors: ImeNotAvailableException.
   */
  Future<String> getActiveImeEngine() => _get('ime/active_engine');

  /**
   * Indicates whether IME input is active at the moment (not if
   * it's available).
   *
   * Potential Errors: ImeNotAvailableException.
   */
  Future<bool> getIsImeActive() => _get('ime/activated');

  /**
   * De-activates the currently-active IME engine.
   *
   * Potential Errors: ImeNotAvailableException.
   */
  Future deactivateIme() => _post('ime/deactivate');

  /**
   * Make an engine that is available (appears on the list returned by
   * getAvailableEngines) active. After this call, the engine will be added
   * to the list of engines loaded in the IME daemon and the input sent using
   * sendKeys will be converted by the active engine. Note that this is a
   * platform-independent method of activating IME (the platform-specific way
   * being using keyboard shortcuts).
   *
   * Potential Errors: ImeActivationFailedException, ImeNotAvailableException.
   */
  Future activateIme(String engine) =>
      _post('ime/activate', params: { 'engine': engine });

  /**
   * Change focus to another frame on the page. If the frame id is null,
   * the server should switch to the page's default content.
   * [id] is the Identifier for the frame to change focus to, and can be
   * a string, number, null, or JSON Object.
   *
   * Potential Errors: NoSuchWindow, NoSuchFrame.
   */
  Future setFrameFocus(id) => _post('frame', params: { 'id': id });

  /**
   * Change focus to another window. The window to change focus to may be
   * specified by [name], which is its server assigned window handle, or
   * the value of its name attribute.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future setWindowFocus(name) =>
      _post('window', params: { 'name': name });

  /**
   * Close the current window.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future closeWindow() => _delete('window');

  /**
   * Retrieve all cookies visible to the current page.
   *
   * The returned List contains Maps with the following keys:
   *
   * 'name' - The name of the cookie.
   *
   * 'value' - The cookie value.
   *
   * The following keys may optionally be present:
   *
   * 'path' - The cookie path.
   *
   * 'domain' - The domain the cookie is visible to.
   *
   * 'secure' - Whether the cookie is a secure cookie.
   *
   * 'expiry' - When the cookie expires, seconds since midnight, 1/1/1970 UTC.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<List<Map>> getCookies() => _get('cookie');

  /**
   * Set a cookie. If the cookie path is not specified, it should be set
   * to "/". Likewise, if the domain is omitted, it should default to the
   * current page's domain. See [getCookies] for the structure of a cookie
   * Map.
   */
  Future setCookie(Map cookie) =>
      _post('cookie', params: { 'cookie': cookie });

  /**
   * Delete all cookies visible to the current page.
   *
   * Potential Errors: InvalidCookieDomain (the cookie's domain is not
   * visible from the current page), NoSuchWindow, UnableToSetCookie (if
   * attempting to set a cookie on a page that does not support cookies,
   * e.g. pages with mime-type text/plain).
   */
  Future deleteCookies() => _delete('cookie');

  /**
   * Delete the cookie with the given [name]. This command should be a no-op
   * if there is no such cookie visible to the current page.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future deleteCookie(String name) => _delete('cookie/$name');

  /**
   * Get the current page source.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<String> getPageSource() => _get('source');

  /**
   * Get the current page title.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<String> getPageTitle() => _get('title');

  /**
   * Search for an element on the page, starting from the document root. The
   * first matching located element will be returned as a WebElement JSON
   * object (a [Map] with an 'ELEMENT' key whose value should be used to
   * identify the element in further requests). The [strategy] should be
   * one of:
   *
   * 'class name' - Returns an element whose class name contains the search
   *    value; compound class names are not permitted.
   *
   * 'css selector' - Returns an element matching a CSS selector.
   *
   * 'id' - Returns an element whose ID attribute matches the search value.
   *
   * 'name' - Returns an element whose NAME attribute matches the search value.
   *
   * 'link text' - Returns an anchor element whose visible text matches the
   *   search value.
   *
   * 'partial link text' - Returns an anchor element whose visible text
   *   partially matches the search value.
   *
   * 'tag name' - Returns an element whose tag name matches the search value.
   *
   * 'xpath' - Returns an element matching an XPath expression.
   *
   * Potential Errors: NoSuchWindow, NoSuchElement, XPathLookupError (if
   * using XPath and the input expression is invalid).
   */
  Future<String> findElement(String strategy, String searchValue) =>
      _post('element', params: { 'using': strategy, 'value' : searchValue });

  /**
   * Search for multiple elements on the page, starting from the document root.
   * The located elements will be returned as WebElement JSON objects. See
   * [findElement] for the locator strategies that each server supports.
   * Elements are be returned in the order located in the DOM.
   *
   * Potential Errors: NoSuchWindow, XPathLookupError.
   */
  Future<List<String>> findElements(String strategy, String searchValue) =>
      _post('elements', params: { 'using': strategy, 'value' : searchValue });

  /**
   * Get the element on the page that currently has focus. The element will
   * be returned as a WebElement JSON object.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<String> getElementWithFocus() => _post('element/active');

  /**
   * Search for an element on the page, starting from element with id [id].
   * The located element will be returned as WebElement JSON objects. See
   * [findElement] for the locator strategies that each server supports.
   *
   * Potential Errors: NoSuchWindow, XPathLookupError.
   */
  Future<String>
      findElementFromId(String id, String strategy, String searchValue) {
    _post('element/$id/element',
              params: { 'using': strategy, 'value' : searchValue });
  }

  /**
   * Search for multiple elements on the page, starting from the element with
   * id [id].The located elements will be returned as WebElement JSON objects.
   * See [findElement] for the locator strategies that each server supports.
   * Elements are be returned in the order located in the DOM.
   *
   * Potential Errors: NoSuchWindow, XPathLookupError.
   */
  Future<List<String>>
      findElementsFromId(String id, String strategy, String searchValue) =>
          _post('element/$id/elements',
              params: { 'using': strategy, 'value' : searchValue });

  /**
   * Click on an element specified by [id].
   *
   * Potential Errors: NoSuchWindow, StaleElementReference, ElementNotVisible
   * (if the referenced element is not visible on the page, either hidden
   * by CSS, or has 0-width or 0-height).
   */
  Future clickElement(String id) => _post('element/$id/click');

  /**
   * Submit a FORM element. The submit command may also be applied to any
   * element that is a descendant of a FORM element.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference.
   */
  Future submit(String id) => _post('element/$id/submit');

  /** Returns the visible text for the element.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference.
   */
  Future<String> getElementText(String id) => _get('element/$id/text');

  /**
   * Send a sequence of key strokes to an element.
   *
   * Any UTF-8 character may be specified, however, if the server does not
   * support native key events, it will simulate key strokes for a standard
   * US keyboard layout. The Unicode Private Use Area code points,
   * 0xE000-0xF8FF, are used to represent pressable, non-text keys:
   *
   * NULL - U+E000
   *
   * Cancel - U+E001
   *
   * Help - U+E002
   *
   * Backspace - U+E003
   *
   * Tab - U+E004
   *
   * Clear - U+E005
   *
   * Return - U+E006
   *
   * Enter - U+E007
   *
   * Shift - U+E008
   *
   * Control - U+E009
   *
   * Alt - U+E00A
   *
   * Pause - U+E00B
   *
   * Escape - U+E00C
   *
   * Space - U+E00D
   *
   * Pageup - U+E00E
   *
   * Pagedown - U+E00F
   *
   * End - U+E010
   *
   * Home - U+E011
   *
   * Left arrow - U+E012
   *
   * Up arrow - U+E013
   *
   * Right arrow - U+E014
   *
   * Down arrow - U+E015
   *
   * Insert - U+E016
   *
   * Delete - U+E017
   *
   * Semicolon - U+E018
   *
   * Equals - U+E019
   *
   * Numpad 0..9 - U+E01A..U+E023
   *
   * Multiply - U+E024
   *
   * Add - U+E025
   *
   * Separator - U+E026
   *
   * Subtract - U+E027
   *
   * Decimal - U+E028
   *
   * Divide - U+E029
   *
   * F1..F12 - U+E031..U+E03C
   *
   * Command/Meta U+E03D
   *
   * The server processes the key sequence as follows:
   *
   * - Each key that appears on the keyboard without requiring modifiers is
   *   sent as a keydown followed by a key up.
   *
   * - If the server does not support native events and must simulate key
   *   strokes with JavaScript, it will generate keydown, keypress, and keyup
   *   events, in that order. The keypress event is only fired when the
   *   corresponding key is for a printable character.
   *
   * - If a key requires a modifier key (e.g. "!" on a standard US keyboard),
   *   the sequence is: modifier down, key down, key up, modifier up, where
   *   key is the ideal unmodified key value (using the previous example,
   *   a "1").
   *
   * - Modifier keys (Ctrl, Shift, Alt, and Command/Meta) are assumed to be
   *  "sticky"; each modifier is held down (e.g. only a keydown event) until
   *   either the modifier is encountered again in the sequence, or the NULL
   *   (U+E000) key is encountered.
   *
   * - Each key sequence is terminated with an implicit NULL key.
   *   Subsequently, all depressed modifier keys are released (with
   *   corresponding keyup events) at the end of the sequence.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference, ElementNotVisible.
   */
  Future sendKeyStrokesToElement(String id, List<String> keys) =>
      _post('element/$id/value', params: { 'value': keys });

  /**
   * Send a sequence of key strokes to the active element. This command is
   * similar to [sendKeyStrokesToElement] command in every aspect except the
   * implicit termination: The modifiers are not released at the end of the
   * call. Rather, the state of the modifier keys is kept between calls,
   * so mouse interactions can be performed while modifier keys are depressed.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future sendKeyStrokes(List<String> keys) =>
      _post('keys', params: { 'value': keys });

  /**
   * Query for an element's tag name, as a lower-case string.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference.
   */
  Future<String> getElementTagName(String id) => _get('element/$id/name');

  /**
   * Clear a TEXTAREA or text INPUT element's value.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference, ElementNotVisible,
   * InvalidElementState.
   */
  Future clearValue(String id) => _post('/element/$id/clear');

  /**
   * Determine if an OPTION element, or an INPUT element of type checkbox
   * or radiobutton is currently selected.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference.
   */
  Future<bool> isSelected(String id) => _get('element/$id/selected');

  /**
   * Determine if an element is currently enabled.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference.
   */
  Future<bool> isEnabled(String id) => _get('element/$id/enabled');

  /**
   * Get the value of an element's attribute, or null if it has no such
   * attribute.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference.
   */
  Future<String> getAttribute(String id, String attribute) =>
      _get('element/$id/attribute/$attribute');

  /**
   * Test if two element IDs refer to the same DOM element.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference.
   */
  Future<bool> areSameElement(String id, String other) =>
      _get('element/$id/equals/$other');

  /**
   * Determine if an element is currently displayed.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference.
   */
  Future<bool> isDiplayed(String id) => _get('element/$id/displayed');

  /**
   * Determine an element's location on the page. The point (0, 0) refers to
   * the upper-left corner of the page. The element's coordinates are returned
   * as a [Map] object with x and y properties.
   *
   * Potential Errors: NoSuchWindow, StaleElementReference.
   */
  Future<Map> getElementLocation(String id) => _get('element/$id/location');

  /**
   * Determine an element's size in pixels. The size will be returned as a
   * [Map] object with width and height properties.
   *
   * Potential Errors: NoSuchWindow, StalElementReference.
   */
  Future<Map> getElementSize(String id) => _get('element/$id/size');

  /**
   * Query the value of an element's computed CSS property. The CSS property
   * to query should be specified using the CSS property name, not the
   * JavaScript property name (e.g. background-color instead of
   * backgroundColor).
   *
   * Potential Errors: NoSuchWindow, StaleElementReference.
   */
  Future<String> getElementCssProperty(String id, String property) =>
      _get('element/$id/css/$property');

  /**
   * Get the current browser orientation ('LANDSCAPE' or 'PORTRAIT').
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<String> getBrowserOrientation() => _get('orientation');

  /**
   * Gets the text of the currently displayed JavaScript alert(), confirm(),
   * or prompt() dialog.
   *
   * Potential Errors: NoAlertPresent.
   */
  Future<String> getAlertText() => _get('alert_text');

  /**
   * Sends keystrokes to a JavaScript prompt() dialog.
   *
   * Potential Errors: NoAlertPresent.
   */
  Future sendKeyStrokesToPrompt(String text) =>
      _post('alert_text', params: { 'text': text });

  /**
   * Accepts the currently displayed alert dialog. Usually, this is equivalent
   * to clicking on the 'OK' button in the dialog.
   *
   * Potential Errors: NoAlertPresent.
   */
  Future acceptAlert() => _post('accept_alert');

  /**
   * Dismisses the currently displayed alert dialog. For confirm() and prompt()
   * dialogs, this is equivalent to clicking the 'Cancel' button. For alert()
   * dialogs, this is equivalent to clicking the 'OK' button.
   *
   * Potential Errors: NoAlertPresent.
   */
  Future dismissAlert() => _post('dismiss_alert');

  /**
   * Move the mouse by an offset of the specificed element. If no element is
   * specified, the move is relative to the current mouse cursor. If an
   * element is provided but no offset, the mouse will be moved to the center
   * of the element. If the element is not visible, it will be scrolled
   * into view.
   */
  Future moveTo(String id, int x, int y) =>
      _post('moveto', params: { 'element': id, 'xoffset': x, 'yoffset' : y});

  /**
   * Click a mouse button (at the coordinates set by the last [moveTo] command).
   * Note that calling this command after calling [buttonDown] and before
   * calling [buttonUp] (or any out-of-order interactions sequence) will yield
   * undefined behaviour).
   *
   * [button] should be 0 for left, 1 for middle, or 2 for right.
   */
  Future clickMouse([button = 0]) =>
      _post('click', params: { 'button' : button });

  /**
   * Click and hold the left mouse button (at the coordinates set by the last
   * [moveTo] command). Note that the next mouse-related command that should
   * follow is [buttonDown]. Any other mouse command (such as [click] or
   * another call to [buttonDown]) will yield undefined behaviour.
   *
   * [button] should be 0 for left, 1 for middle, or 2 for right.
   */
  Future buttonDown([button = 0]) =>
      _post('click', params: { 'button' : button });

  /**
   * Releases the mouse button previously held (where the mouse is currently
   * at). Must be called once for every [buttonDown] command issued. See the
   * note in [click] and [buttonDown] about implications of out-of-order
   * commands.
   *
   * [button] should be 0 for left, 1 for middle, or 2 for right.
   */
  Future buttonUp([button = 0]) =>
      _post('click', params: { 'button' : button });

  /** Double-clicks at the current mouse coordinates (set by [moveTo]). */
  Future doubleClick() => _post('doubleclick');

  /** Single tap on the touch enabled device on the element with id [id]. */
  Future touchClick(String id) =>
      _post('touch/click', params: { 'element': id });

  /** Finger down on the screen. */
  Future touchDown(int x, int y) =>
      _post('touch/down', params: { 'x': x, 'y': y });

  /** Finger up on the screen. */
  Future touchUp(int x, int y) =>
      _post('touch/up', params: { 'x': x, 'y': y });

  /** Finger move on the screen. */
  Future touchMove(int x, int y) =>
      _post('touch/move', params: { 'x': x, 'y': y });

  /**
   * Scroll on the touch screen using finger based motion events. If [id] is
   * specified, scrolling will start at a particular screen location.
   */
  Future touchScroll(int xOffset, int yOffset, [String id = null]) {
    if (id == null) {
      return _post('touch/scroll',
          params: { 'xoffset': xOffset, 'yoffset': yOffset });
    } else {
      return _post('touch/scroll',
          params: { 'element': id, 'xoffset': xOffset, 'yoffset': yOffset });
    }
  }

  /** Double tap on the touch screen using finger motion events. */
  Future touchDoubleClick(String id) =>
      _post('touch/doubleclick', params: { 'element': id });

  /** Long press on the touch screen using finger motion events. */
  Future touchLongClick(String id) =>
      _post('touch/longclick', params: { 'element': id });

  /**
   * Flick on the touch screen using finger based motion events, starting
   * at a particular screen location. [speed] is in pixels-per-second.
   */
  Future touchFlickFrom(String id, int xOffset, int yOffset, int speed) =>
          _post('touch/flick',
              params: { 'element': id, 'xoffset': xOffset, 'yoffset': yOffset,
                        'speed': speed });

  /**
   * Flick on the touch screen using finger based motion events. Use this
   * instead of [touchFlickFrom] if you don'tr care where the flick starts.
   */
  Future touchFlick(int xSpeed, int ySpeed) =>
      _post('touch/flick', params: { 'xSpeed': xSpeed, 'ySpeed': ySpeed });

  /**
   * Get the current geo location. Returns a [Map] with latitude,
   * longitude and altitude properties.
   */
  Future<Map> getGeolocation() => _get('location');

  /** Set the current geo location. */
  Future setLocation(double latitude, double longitude, double altitude) =>
          _post('location', params:
              { 'latitude': latitude,
                'longitude': longitude,
                'altitude': altitude });

  /**
   * Get all keys of the local storage. Completes with [null] if there
   * are no keys or the keys could not be retrieved.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<List<String>> getLocalStorageKeys() => _get('local_storage');

  /**
   * Set the local storage item for the given key.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future setLocalStorageItem(String key, String value) =>
      _post('local_storage', params: { 'key': key, 'value': value });

  /**
   * Clear the local storage.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future clearLocalStorage() => _delete('local_storage');

  /**
   * Get the local storage item for the given key.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<String> getLocalStorageValue(String key) =>
      _get('local_storage/key/$key');

  /**
   * Delete the local storage item for the given key.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future deleteLocalStorageValue(String key) =>
      _delete('local_storage/key/$key');

  /**
   * Get the number of items in the local storage.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<int> getLocalStorageCount() => _get('local_storage/size');

  /**
   * Get all keys of the session storage.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<List<String>> getSessionStorageKeys() => _get('session_storage');

  /**
   * Set the sessionstorage item for the given key.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future setSessionStorageItem(String key, String value) =>
      _post('session_storage', params: { 'key': key, 'value': value });

  /**
   * Clear the session storage.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future clearSessionStorage() => _delete('session_storage');

  /**
   * Get the session storage item for the given key.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<String> getSessionStorageValue(String key) =>
      _get('session_storage/key/$key');

  /**
   * Delete the session storage item for the given key.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future deleteSessionStorageValue(String key) =>
      _delete('session_storage/key/$key');

  /**
   * Get the number of items in the session storage.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<String> getSessionStorageCount() => _get('session_storage/size');

  /** Get available log types ('client', 'driver', 'browser', 'server'). */
  Future<List<String>> getLogTypes() => _get('log/types');

  /**
   * Get the log for a given log type. Log buffer is reset after each request.
   * Each log entry is a [Map] with these fields:
   *
   * 'timestamp' (int) - The timestamp of the entry.
   * 'level' (String) - The log level of the entry, for example, "INFO".
   * 'message' (String) - The log message.
   */
  Future<List<Map>> getLogs(String type) =>
      _post('log', params: { 'type': type });
}
