// 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:async';
import 'dart:io';
import 'dart:json' as json;
import 'dart:uri';

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.then((_session) {
 *       session = _session;
 *       return session.setUrl('http://my.web.site.com');
 *    }).then((_) {
 *      return session.findElement('id', 'username');
 *    }).then((element) {
 *      id = element['ELEMENT'];
 *      return session.sendKeyStrokesToElement(id,
 *          [ 'j', 'o', 'e', ' ', 'u', 's', 'e', 'r' ]);
 *    }).then((_) {
 *      return session.submit(id);
 *    }).then((_) {
 *      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';
  }

  void _failRequest(Completer completer, error, [stackTrace]) {
    if (completer != null) {
      var trace = stackTrace != null ? stackTrace : getAttachedStackTrace(error);
      completer.completeError(new WebDriverError(-1, error), trace);
    }
  }

  /**
   * 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, params, Function customHandler}) {
    var status = 0;
    var results = null;
    var message = null;
    if (successCodes == null) {
      successCodes = [ 200, 204 ];
    }
    try {
      var path = command;
      if (params != null) {
        if (params is num || params is String) {
          path = '$path/$params';
          params = null;
        } else if (http_method != 'POST') {
          throw new Exception(
            'The http method called for ${command} is ${http_method} but it '
            'must be POST if you want to pass the JSON params '
            '${json.stringify(params)}');
        }
      }

      var client = new HttpClient();
      client.open(http_method, _host, _port, path).then((req) {
        req.followRedirects = false;
        req.headers.add(HttpHeaders.ACCEPT, "application/json");
        req.headers.add(
            HttpHeaders.CONTENT_TYPE, 'application/json;charset=UTF-8');
        if (params != null) {
          var body = json.stringify(params);
          req.write(body);
        }
        req.close().then((rsp) {
          List<int> body = new List<int>();
          rsp.listen(body.addAll, onDone: () {
            var value = null;
            // 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 with trim().
            // 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.
            results = new String.fromCharCodes(body).trim();
            if (!successCodes.contains(rsp.statusCode)) {
              _failRequest(completer, 
                  'Unexpected response ${rsp.statusCode}; $results');
              completer = null;
              return;
            }
            if (status == 0 && results.length > 0) {
              // 4xx responses send plain text; others send JSON.
              if (rsp.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(rsp, value);
              } else if (completer != null) {
                completer.complete(value);
              }
            }
          }, onError: (error) {
            _failRequest(completer, error);
            completer = null;
          });
        })
        .catchError((error) {
          _failRequest(completer, error);
          completer = null;
        });
      })
      .catchError((error) {
        _failRequest(completer, error);
        completer = null;
      });
    } catch (e, s) {
      _failRequest(completer, e, s);
      completer = null;
    }
  }

  Future _get(String extraPath,
      [Completer completer, Function customHandler]) {
    if (completer == null) completer = new Completer();
    _serverRequest('GET', '${_path}/$extraPath', completer,
        customHandler: customHandler);
    return completer.future;
  }

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

  Future _delete(String extraPath) {
    var completer = new Completer();
    _serverRequest('DELETE', '${_path}/$extraPath', completer);
    return completer.future;
  }
}

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', completer,
        successCodes: [ 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();
    return _get('sessions', completer, (r, v) {
      var _sessions = [];
      for (var session in v) {
        var url = 'http://${this._host}:${this._port}${this._path}/'
            'session/${session["id"]}';
        _sessions.add(new WebDriverSession.fromUrl(url));
      }
      completer.complete(_sessions);
    });
  }

  /** 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. Note that this is flaky and often
   * has no effect.
   *
   * Potential Errors:
   *   NoSuchWindow - If the specified window cannot be found.
   */
  Future<String> setSize(int width, int height) =>
      _post('size', { 'width': width, 'height': height });

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

  /**
   * Set the window position. Note that this is flaky and often
   * has no effect.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future setPosition(int x, int y) =>
      _post('position', { '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', { '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', { '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', { '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', { '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', { '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]) {
    if (args == null) args = [];
    return _post('execute', { '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]) {
    if (args == null) args = [];
    return _post('execute_async', { 'script': script, 'args': args });
  }

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

  /**
   * 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', { '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', { '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', { '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', { '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', { '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', { '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', { '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', { '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', { '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', { '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', { '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', { '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', { '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', { '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', { 'element': id });

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

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

  /** Finger move on the screen. */
  Future touchMove(int x, int y) => _post('touch/move', { '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', { 'xoffset': xOffset, 'yoffset': yOffset });
    } else {
      return _post('touch/scroll',
          { 'element': id, 'xoffset': xOffset, 'yoffset': yOffset });
    }
  }

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

  /** Long press on the touch screen using finger motion events. */
  Future touchLongClick(String id) =>
      _post('touch/longclick', { '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',
              { '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', { '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',
              { 'latitude': latitude,
                'longitude': longitude,
                'altitude': altitude });

  /**
   * Only a few drivers actually support the JSON storage commands.
   * Currently it looks like this is the Android and iPhone drivers only.
   * For the rest, we can achieve a similar effect with Javascript
   * execution. The flag below is used to control whether to do this.
   */
  bool useJavascriptForStorageAPIs = true;

  /**
   * 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() {
    if (useJavascriptForStorageAPIs) {
      return execute(
          'var rtn = [];'
          'for (var i = 0; i < window.localStorage.length; i++)'
          '  rtn.push(window.localStorage.key(i));'
          'return rtn;'); 
    } else {
      return _get('local_storage');
    }
  }

  /**
   * Set the local storage item for the given key.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future setLocalStorageItem(String key, String value) {
    if (useJavascriptForStorageAPIs) {
      return execute('window.localStorage.setItem(arguments[0], arguments[1]);',
          [key, value]); 
    } else {
      return _post('local_storage', { 'key': key, 'value': value });
    }
  }

  /**
   * Clear the local storage.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future clearLocalStorage() {
    if (useJavascriptForStorageAPIs) {
      return execute('return window.localStorage.clear();');
    } else {
      return _delete('local_storage');
    }
  }

  /**
   * Get the local storage item for the given key.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<String> getLocalStorageValue(String key) {
    if (useJavascriptForStorageAPIs) {
      return execute('return window.localStorage.getItem(arguments[0]);',
          [key]); 
    } else {
      return _get('local_storage/key/$key');
    }
  }

  /**
   * Delete the local storage item for the given key.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future deleteLocalStorageValue(String key) {
    if (useJavascriptForStorageAPIs) {
      return execute('return window.localStorage.removeItem(arguments[0]);',
          [key]); 
    } else {
      return _delete('local_storage/key/$key');
    }
  }

  /**
   * Get the number of items in the local storage.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<int> getLocalStorageCount() {
    if (useJavascriptForStorageAPIs) {
      return execute('return window.localStorage.length;'); 
    } else {
      return _get('local_storage/size');
    }
  }

  /**
   * Get all keys of the session storage.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<List<String>> getSessionStorageKeys() {
    if (useJavascriptForStorageAPIs) {
      return execute(
          'var rtn = [];'
          'for (var i = 0; i < window.sessionStorage.length; i++)'
          '  rtn.push(window.sessionStorage.key(i));'
          'return rtn;'); 
    } else {
      return _get('session_storage');
    }
  }

  /**
   * Set the sessionstorage item for the given key.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future setSessionStorageItem(String key, String value) {
    if (useJavascriptForStorageAPIs) {
      return execute(
          'window.sessionStorage.setItem(arguments[0], arguments[1]);',
              [key, value]); 
    } else {
      return _post('session_storage', { 'key': key, 'value': value });
    }
  }

  /**
   * Clear the session storage.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future clearSessionStorage() {
    if (useJavascriptForStorageAPIs) {
      return execute('window.sessionStorage.clear();');
    } else {
      return _delete('session_storage');
    }
  }

  /**
   * Get the session storage item for the given key.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<String> getSessionStorageValue(String key) {
    if (useJavascriptForStorageAPIs) {
      return execute('return window.sessionStorage.getItem(arguments[0]);',
          [key]); 
    } else {
      return _get('session_storage/key/$key');
    }
  }

  /**
   * Delete the session storage item for the given key.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future deleteSessionStorageValue(String key) {
    if (useJavascriptForStorageAPIs) {
      return execute('return window.sessionStorage.removeItem(arguments[0]);',
          [key]); 
    } else {
      return _delete('session_storage/key/$key');
    }
  }

  /**
   * Get the number of items in the session storage.
   *
   * Potential Errors: NoSuchWindow.
   */
  Future<String> getSessionStorageCount() {
    if (useJavascriptForStorageAPIs) {
      return execute('return window.sessionStorage.length;');
    } else {
      return _get('session_storage/size');
    }
  }

  /**
   * Get available log types ('client', 'driver', 'browser', 'server').
   * This works with Firefox but Chrome returns a 500 response due to a 
   * bad cast.
   */
  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.
   *
   * This works with Firefox but Chrome returns a 500 response due to a 
   * bad cast.
   */
  Future<List<Map>> getLogs(String type) => _post('log', { 'type': type });
}
