(function() {
  let sourceNameIdx = 0;

  /**
   * Builder for creating a sequence of actions
   * The default tick duration is set to 16ms, which is one frame time based on
   * 60Hz display.
   */
  function Actions(defaultTickDuration=16) {
    this.sourceTypes = new Map([["key", KeySource],
                                ["pointer", PointerSource],
                                ["none", GeneralSource]]);
    this.sources = new Map();
    this.sourceOrder = [];
    for (let sourceType of this.sourceTypes.keys()) {
      this.sources.set(sourceType, new Map());
    }
    this.currentSources = new Map();
    for (let sourceType of this.sourceTypes.keys()) {
      this.currentSources.set(sourceType, null);
    }
    this.createSource("none");
    this.tickIdx = 0;
    this.defaultTickDuration = defaultTickDuration;
  }

  Actions.prototype = {
    ButtonType: {
      LEFT: 0,
      MIDDLE: 1,
      RIGHT: 2,
      BACK: 3,
      FORWARD: 4,
    },

    /**
     * Generate the action sequence suitable for passing to
     * test_driver.action_sequence
     *
     * @returns {Array} Array of WebDriver-compatible actions sequences
     */
    serialize: function() {
      let actions = [];
      for (let [sourceType, sourceName] of this.sourceOrder) {
        let source = this.sources.get(sourceType).get(sourceName);
        let serialized = source.serialize(this.tickIdx + 1, this.defaultTickDuration);
        if (serialized) {
          serialized.id = sourceName;
          actions.push(serialized);
        }
      }
      return actions;
    },

    /**
     * Generate and send the action sequence
     *
     * @returns {Promise} fulfilled after the sequence is executed,
     *                    rejected if any actions fail.
     */
    send: function() {
      let actions;
      try {
        actions = this.serialize();
      } catch(e) {
        return Promise.reject(e);
      }
      return test_driver.action_sequence(actions);
    },

    /**
     * Get the action source with a particular source type and name.
     * If no name is passed, a new source with the given type is
     * created.
     *
     * @param {String} type - Source type ('none', 'key', or 'pointer')
     * @param {String?} name - Name of the source
     * @returns {Source} Source object for that source.
     */
    getSource: function(type, name) {
      if (!this.sources.has(type)) {
        throw new Error(`${type} is not a valid action type`);
      }
      if (name === null || name === undefined) {
        name = this.currentSources.get(type);
      }
      if (name === null || name === undefined) {
        return this.createSource(type, null);
      }
      return this.sources.get(type).get(name);
    },

    setSource: function(type, name) {
      if (!this.sources.has(type)) {
        throw new Error(`${type} is not a valid action type`);
      }
      if (!this.sources.get(type).has(name)) {
        throw new Error(`${name} is not a valid source for ${type}`);
      }
      this.currentSources.set(type, name);
      return this;
    },

    /**
     * Add a new key input source with the given name
     *
     * @param {String} name - Name of the key source
     * @param {Bool} set - Set source as the default key source
     * @returns {Actions}
     */
    addKeyboard: function(name, set=true) {
      this.createSource("key", name);
      if (set) {
        this.setKeyboard(name);
      }
      return this;
    },

    /**
     * Set the current default key source
     *
     * @param {String} name - Name of the key source
     * @returns {Actions}
     */
    setKeyboard: function(name) {
      this.setSource("key", name);
      return this;
    },

    /**
     * Add a new pointer input source with the given name
     *
     * @param {String} type - Name of the key source
     * @param {String} pointerType - Type of pointing device
     * @param {Bool} set - Set source as the default key source
     * @returns {Actions}
     */
    addPointer: function(name, pointerType="mouse", set=true) {
      this.createSource("pointer", name, {pointerType: pointerType});
      if (set) {
        this.setPointer(name);
      }
      return this;
    },

    /**
     * Set the current default pointer source
     *
     * @param {String} name - Name of the pointer source
     * @returns {Actions}
     */
    setPointer: function(name) {
      this.setSource("pointer", name);
      return this;
    },

    createSource: function(type, name, parameters={}) {
      if (!this.sources.has(type)) {
        throw new Error(`${type} is not a valid action type`);
      }
      let sourceNames = new Set();
      for (let [_, name] of this.sourceOrder) {
        sourceNames.add(name);
      }
      if (!name) {
        do {
          name = "" + sourceNameIdx++;
        } while (sourceNames.has(name))
      } else {
        if (sourceNames.has(name)) {
          throw new Error(`Alreay have a source of type ${type} named ${name}.`);
        }
      }
      this.sources.get(type).set(name, new (this.sourceTypes.get(type))(parameters));
      this.currentSources.set(type, name);
      this.sourceOrder.push([type, name]);
      return this.sources.get(type).get(name);
    },

    /**
     * Insert a new actions tick
     *
     * @param {Number?} duration - Minimum length of the tick in ms.
     * @returns {Actions}
     */
    addTick: function(duration) {
      this.tickIdx += 1;
      if (duration) {
        this.pause(duration);
      }
      return this;
    },

    /**
     * Add a pause to the current tick
     *
     * @param {Number?} duration - Minimum length of the tick in ms.
     * @param {String} sourceType - source type
     * @param {String?} sourceName - Named key or pointer source to use or null for the default
     *                               key or pointer source
     * @returns {Actions}
     */
    pause: function(duration=0, sourceType="none", {sourceName=null}={}) {
      if (sourceType=="none")
        this.getSource("none").addPause(this, duration);
      else
        this.getSource(sourceType, sourceName).addPause(this, duration);
      return this;
    },

    /**
     * Create a keyDown event for the current default key source
     *
     * @param {String} key - Key to press
     * @param {String?} sourceName - Named key source to use or null for the default key source
     * @returns {Actions}
     */
    keyDown: function(key, {sourceName=null}={}) {
      let source = this.getSource("key", sourceName);
      source.keyDown(this, key);
      return this;
    },

    /**
     * Create a keyDown event for the current default key source
     *
     * @param {String} key - Key to release
     * @param {String?} sourceName - Named key source to use or null for the default key source
     * @returns {Actions}
     */
    keyUp: function(key, {sourceName=null}={}) {
      let source = this.getSource("key", sourceName);
      source.keyUp(this, key);
      return this;
    },

    /**
     * Create a pointerDown event for the current default pointer source
     *
     * @param {String} button - Button to press
     * @param {String?} sourceName - Named pointer source to use or null for the default
     *                               pointer source
     * @returns {Actions}
     */
    pointerDown: function({button=this.ButtonType.LEFT, sourceName=null}={}) {
      let source = this.getSource("pointer", sourceName);
      source.pointerDown(this, button);
      return this;
    },

    /**
     * Create a pointerUp event for the current default pointer source
     *
     * @param {String} button - Button to release
     * @param {String?} sourceName - Named pointer source to use or null for the default pointer
     *                               source
     * @returns {Actions}
     */
    pointerUp: function({button=this.ButtonType.LEFT, sourceName=null}={}) {
      let source = this.getSource("pointer", sourceName);
      source.pointerUp(this, button);
      return this;
    },

    /**
     * Create a move event for the current default pointer source
     *
     * @param {Number} x - Destination x coordinate
     * @param {Number} y - Destination y coordinate
     * @param {String|Element} origin - Origin of the coordinate system.
     *                                  Either "pointer", "viewport" or an Element
     * @param {Number?} duration - Time in ms for the move
     * @param {String?} sourceName - Named pointer source to use or null for the default pointer
     *                               source
     * @returns {Actions}
     */
    pointerMove: function(x, y,
                          {origin="viewport", duration, sourceName=null}={}) {
      let source = this.getSource("pointer", sourceName);
      source.pointerMove(this, x, y, duration, origin);
      return this;
    },
  };

  function GeneralSource() {
    this.actions = new Map();
  }

  GeneralSource.prototype = {
    serialize: function(tickCount, defaultTickDuration) {
      let actions = [];
      let data = {"type": "none", "actions": actions};
      for (let i=0; i<tickCount; i++) {
        if (this.actions.has(i)) {
          actions.push(this.actions.get(i));
        } else {
          actions.push({"type": "pause", duration: defaultTickDuration});
        }
      }
      return data;
    },

    addPause: function(actions, duration) {
      let tick = actions.tickIdx;
      if (this.actions.has(tick)) {
        throw new Error(`Already have a pause action for the current tick`);
      }
      this.actions.set(tick, {type: "pause", duration: duration});
    },
  };

  function KeySource() {
    this.actions = new Map();
  }

  KeySource.prototype = {
    serialize: function(tickCount) {
      if (!this.actions.size) {
        return undefined;
      }
      let actions = [];
      let data = {"type": "key", "actions": actions};
      for (let i=0; i<tickCount; i++) {
        if (this.actions.has(i)) {
          actions.push(this.actions.get(i));
        } else {
          actions.push({"type": "pause"});
        }
      }
      return data;
    },

    keyDown: function(actions, key) {
      let tick = actions.tickIdx;
      if (this.actions.has(tick)) {
        tick = actions.addTick().tickIdx;
      }
      this.actions.set(tick, {type: "keyDown", value: key});
    },

    keyUp: function(actions, key) {
      let tick = actions.tickIdx;
      if (this.actions.has(tick)) {
        tick = actions.addTick().tickIdx;
      }
      this.actions.set(tick, {type: "keyUp", value: key});
    },

    addPause: function(actions, duration) {
      let tick = actions.tickIdx;
      if (this.actions.has(tick)) {
        tick = actions.addTick().tickIdx;
      }
      this.actions.set(tick, {type: "pause", duration: duration});
    },
  };

  function PointerSource(parameters={pointerType: "mouse"}) {
    let pointerType = parameters.pointerType || "mouse";
    if (!["mouse", "pen", "touch"].includes(pointerType)) {
      throw new Error(`Invalid pointerType ${pointerType}`);
    }
    this.type = pointerType;
    this.actions = new Map();
  }

  PointerSource.prototype = {
    serialize: function(tickCount) {
      if (!this.actions.size) {
        return undefined;
      }
      let actions = [];
      let data = {"type": "pointer", "actions": actions, "parameters": {"pointerType": this.type}};
      for (let i=0; i<tickCount; i++) {
        if (this.actions.has(i)) {
          actions.push(this.actions.get(i));
        } else {
          actions.push({"type": "pause"});
        }
      }
      return data;
    },

    pointerDown: function(actions, button) {
      let tick = actions.tickIdx;
      if (this.actions.has(tick)) {
        tick = actions.addTick().tickIdx;
      }
      this.actions.set(tick, {type: "pointerDown", button});
    },

    pointerUp: function(actions, button) {
      let tick = actions.tickIdx;
      if (this.actions.has(tick)) {
        tick = actions.addTick().tickIdx;
      }
      this.actions.set(tick, {type: "pointerUp", button});
    },

    pointerMove: function(actions, x, y, duration, origin) {
      let tick = actions.tickIdx;
      if (this.actions.has(tick)) {
        tick = actions.addTick().tickIdx;
      }
      this.actions.set(tick, {type: "pointerMove", x, y, origin});
      if (duration) {
        this.actions.get(tick).duration = duration;
      }
    },

    addPause: function(actions, duration) {
      let tick = actions.tickIdx;
      if (this.actions.has(tick)) {
        tick = actions.addTick().tickIdx;
      }
      this.actions.set(tick, {type: "pause", duration: duration});
    },
  };

  test_driver.Actions = Actions;
})();
