// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

/**
 * @fileoverview Atoms for simulating user actions against the DOM.
 * The bot.action namespace is required since these atoms would otherwise form a
 * circular dependency between bot.dom and bot.events.
 *
 */

goog.provide('bot.action');

goog.require('bot');
goog.require('bot.Device');
goog.require('bot.Error');
goog.require('bot.ErrorCode');
goog.require('bot.Keyboard');
goog.require('bot.Mouse');
goog.require('bot.Touchscreen');
goog.require('bot.dom');
goog.require('bot.events');
goog.require('goog.array');
goog.require('goog.dom.TagName');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Vec2');
goog.require('goog.style');
goog.require('goog.userAgent');
goog.require('goog.userAgent.product');
goog.require('goog.utils');


/**
 * Throws an exception if an element is not shown to the user, ignoring its
 * opacity.

 *
 * @param {!Element} element The element to check.
 * @see bot.dom.isShown.
 * @private
 */
bot.action.checkShown_ = function (element) {
  if (!bot.dom.isShown(element, /*ignoreOpacity=*/true)) {
    throw new bot.Error(bot.ErrorCode.ELEMENT_NOT_VISIBLE,
      'Element is not currently visible and may not be manipulated');
  }
};


/**
 * Throws an exception if the given element cannot be interacted with.
 *
 * @param {!Element} element The element to check.
 * @throws {bot.Error} If the element cannot be interacted with.
 * @see bot.dom.isInteractable.
 * @private
 */
bot.action.checkInteractable_ = function (element) {
  if (!bot.dom.isInteractable(element)) {
    throw new bot.Error(bot.ErrorCode.INVALID_ELEMENT_STATE,
      'Element is not currently interactable and may not be manipulated');

  }
};


/**
 * Clears the given `element` if it is a editable text field.
 *
 * @param {!Element} element The element to clear.
 * @throws {bot.Error} If the element is not an editable text field.
 */
bot.action.clear = function (element) {
  bot.action.checkInteractable_(element);
  if (!bot.dom.isEditable(element)) {
    throw new bot.Error(bot.ErrorCode.INVALID_ELEMENT_STATE,
      'Element must be user-editable in order to clear it.');
  }

  if (element.value) {
    bot.action.LegacyDevice_.focusOnElement(element);
    if (goog.userAgent.IE && bot.dom.isInputType(element, 'range')) {
      var min = element.min ? element.min : 0;
      var max = element.max ? element.max : 100;
      element.value = (max < min) ? min : min + (max - min) / 2;
    } else {
      element.value = '';
    }
    bot.events.fire(element, bot.events.EventType.CHANGE);
    if (goog.userAgent.IE) {
      bot.events.fire(element, bot.events.EventType.BLUR);
    }
    var body = bot.getDocument().body;
    if (body) {
      bot.action.LegacyDevice_.focusOnElement(body);
    } else {
      throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR,
        'Cannot unfocus element after clearing.');
    }
  } else if (bot.dom.isElement(element, goog.dom.TagName.INPUT) &&
    (element.getAttribute('type') && element.getAttribute('type').toLowerCase() == "number")) {
    // number input fields that have invalid inputs
    // report their value as empty string with no way to tell if there is a
    // current value or not
    bot.action.LegacyDevice_.focusOnElement(element);
    element.value = '';
  } else if (bot.dom.isContentEditable(element)) {
    // A single space is required, if you put empty string here you'll not be
    // able to interact with this element anymore in Firefox.
    bot.action.LegacyDevice_.focusOnElement(element);
    if (goog.userAgent.GECKO) {
      element.textContent = ' ';
    } else {
      element.textContent = '';
    }
    var body = bot.getDocument().body;
    if (body) {
      bot.action.LegacyDevice_.focusOnElement(body);
    } else {
      throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR,
        'Cannot unfocus element after clearing.');
    }
    // contentEditable does not generate onchange event.
  }
};


/**
 * Focuses on the given element if it is not already the active element.
 *
 * @param {!Element} element The element to focus on.
 */
bot.action.focusOnElement = function (element) {
  bot.action.checkInteractable_(element);
  bot.action.LegacyDevice_.focusOnElement(element);
};


/**
 * Types keys on the given `element` with a virtual keyboard.
 *
 * <p>Callers can pass in a string, a key in bot.Keyboard.Key, or an array
 * of strings or keys. If a modifier key is provided, it is pressed but not
 * released, until it is either is listed again or the function ends.
 *
 * <p>Example:
 *   bot.keys.type(element, ['ab', bot.Keyboard.Key.LEFT,
 *                           bot.Keyboard.Key.SHIFT, 'cd']);
 *
 * @param {!Element} element The element receiving the event.
 * @param {(string|!bot.Keyboard.Key|!Array.<(string|!bot.Keyboard.Key)>)}
 *    values Value or values to type on the element.
 * @param {bot.Keyboard=} opt_keyboard Keyboard to use; if not provided,
 *    constructs one.
 * @param {boolean=} opt_persistModifiers Whether modifier keys should remain
 *     pressed when this function ends.
 * @throws {bot.Error} If the element cannot be interacted with.
 */
bot.action.type = function (
  element, values, opt_keyboard, opt_persistModifiers) {
  // If the element has already been brought into focus somehow, typing is
  // always allowed to proceed. Otherwise, we require the element be in an
  // "interactable" state. For example, an element that is hidden by overflow
  // can be typed on, so long as the user first tabs to it or the app calls
  // focus() on the element first.
  if (element != bot.dom.getActiveElement(element)) {
    bot.action.checkInteractable_(element);
    bot.action.scrollIntoView(element);
  }

  var keyboard = opt_keyboard || new bot.Keyboard();
  keyboard.moveCursor(element);

  function typeValue(value) {
    if (typeof value === 'string') {
      goog.array.forEach(value.split(''), function (ch) {
        var keyShiftPair = bot.Keyboard.Key.fromChar(ch);
        var shiftIsPressed = keyboard.isPressed(bot.Keyboard.Keys.SHIFT);
        if (keyShiftPair.shift && !shiftIsPressed) {
          keyboard.pressKey(bot.Keyboard.Keys.SHIFT);
        }
        keyboard.pressKey(keyShiftPair.key);
        keyboard.releaseKey(keyShiftPair.key);
        if (keyShiftPair.shift && !shiftIsPressed) {
          keyboard.releaseKey(bot.Keyboard.Keys.SHIFT);
        }
      });
    } else if (goog.array.contains(bot.Keyboard.MODIFIERS, value)) {
      if (keyboard.isPressed(/** @type {!bot.Keyboard.Key} */(value))) {
        keyboard.releaseKey(value);
      } else {
        keyboard.pressKey(value);
      }
    } else {
      keyboard.pressKey(value);
      keyboard.releaseKey(value);
    }
  }

  // mobile safari (iPhone / iPad). one cannot 'type' in a date field
  // chrome implements this, but desktop Safari doesn't, what's webkit again?
  if ((!(goog.userAgent.product.SAFARI && !goog.userAgent.MOBILE)) &&
    goog.userAgent.WEBKIT && element.type == 'date') {
    var val = Array.isArray(values) ? values = values.join("") : values;
    var datePattern = /\d{4}-\d{2}-\d{2}/;
    if (val.match(datePattern)) {
      // The following events get fired on iOS first
      if (goog.userAgent.MOBILE && goog.userAgent.product.SAFARI) {
        bot.events.fire(element, bot.events.EventType.TOUCHSTART);
        bot.events.fire(element, bot.events.EventType.TOUCHEND);
      }
      bot.events.fire(element, bot.events.EventType.FOCUS);
      element.value = val.match(datePattern)[0];
      bot.events.fire(element, bot.events.EventType.CHANGE);
      bot.events.fire(element, bot.events.EventType.BLUR);
      return;
    }
  }

  if (Array.isArray(values)) {
    goog.array.forEach(values, typeValue);
  } else {
    typeValue(values);
  }

  if (!opt_persistModifiers) {
    // Release all the modifier keys.
    goog.array.forEach(bot.Keyboard.MODIFIERS, function (key) {
      if (keyboard.isPressed(key)) {
        keyboard.releaseKey(key);
      }
    });
  }
};


/**
 * Submits the form containing the given `element`.
 *
 * <p>Note this function submits the form, but does not simulate user input
 * (a click or key press).
 *
 * @param {!Element} element The element to submit.
 * @deprecated Click on a submit button or type ENTER in a text box instead.
 */
bot.action.submit = function (element) {
  var form = bot.action.LegacyDevice_.findAncestorForm(element);
  if (!form) {
    throw new bot.Error(bot.ErrorCode.NO_SUCH_ELEMENT,
      'Element was not in a form, so could not submit.');
  }
  bot.action.LegacyDevice_.submitForm(element, form);
};


/**
 * Moves the mouse over the given `element` with a virtual mouse.
 *
 * @param {!Element} element The element to click.
 * @param {goog.math.Coordinate=} opt_coords Mouse position relative to the
 *   element.
 * @param {bot.Mouse=} opt_mouse Mouse to use; if not provided, constructs one.
 * @throws {bot.Error} If the element cannot be interacted with.
 */
bot.action.moveMouse = function (element, opt_coords, opt_mouse) {
  var coords = bot.action.prepareToInteractWith_(element, opt_coords);
  var mouse = opt_mouse || new bot.Mouse();
  mouse.move(element, coords);
};


/**
 * Clicks on the given `element` with a virtual mouse.
 *
 * @param {!Element} element The element to click.
 * @param {goog.math.Coordinate=} opt_coords Mouse position relative to the
 *   element.
 * @param {bot.Mouse=} opt_mouse Mouse to use; if not provided, constructs one.
 * @param {boolean=} opt_force Whether the release event should be fired even if the
 *     element is not interactable.
 * @throws {bot.Error} If the element cannot be interacted with.
 */
bot.action.click = function (element, opt_coords, opt_mouse, opt_force) {
  var coords = bot.action.prepareToInteractWith_(element, opt_coords);
  var mouse = opt_mouse || new bot.Mouse();
  mouse.move(element, coords);
  mouse.pressButton(bot.Mouse.Button.LEFT);
  mouse.releaseButton(opt_force);
};


/**
 * Right-clicks on the given `element` with a virtual mouse.
 *
 * @param {!Element} element The element to click.
 * @param {goog.math.Coordinate=} opt_coords Mouse position relative to the
 *   element.
 * @param {bot.Mouse=} opt_mouse Mouse to use; if not provided, constructs one.
 * @throws {bot.Error} If the element cannot be interacted with.
 */
bot.action.rightClick = function (element, opt_coords, opt_mouse) {
  var coords = bot.action.prepareToInteractWith_(element, opt_coords);
  var mouse = opt_mouse || new bot.Mouse();
  mouse.move(element, coords);
  mouse.pressButton(bot.Mouse.Button.RIGHT);
  mouse.releaseButton();
};


/**
 * Double-clicks on the given `element` with a virtual mouse.
 *
 * @param {!Element} element The element to click.
 * @param {goog.math.Coordinate=} opt_coords Mouse position relative to the
 *   element.
 * @param {bot.Mouse=} opt_mouse Mouse to use; if not provided, constructs one.
 * @throws {bot.Error} If the element cannot be interacted with.
 */
bot.action.doubleClick = function (element, opt_coords, opt_mouse) {
  var coords = bot.action.prepareToInteractWith_(element, opt_coords);
  var mouse = opt_mouse || new bot.Mouse();
  mouse.move(element, coords);
  mouse.pressButton(bot.Mouse.Button.LEFT);
  mouse.releaseButton();
  mouse.pressButton(bot.Mouse.Button.LEFT);
  mouse.releaseButton();
};


/**
 * Double-clicks on the given `element` with a virtual mouse.
 *
 * @param {!Element} element The element to click.
 * @param {goog.math.Coordinate=} opt_coords Mouse position relative to the
 *   element.
 * @param {bot.Mouse=} opt_mouse Mouse to use; if not provided, constructs one.
 * @throws {bot.Error} If the element cannot be interacted with.
 */
bot.action.doubleClick2 = function (element, opt_coords, opt_mouse) {
  var coords = bot.action.prepareToInteractWith_(element, opt_coords);
  var mouse = opt_mouse || new bot.Mouse();
  mouse.move(element, coords);
  mouse.pressButton(bot.Mouse.Button.LEFT, 2);
  mouse.releaseButton(true, 2);
};


/**
 * Scrolls the mouse wheel on the given `element` with a virtual mouse.
 *
 * @param {!Element} element The element to scroll the mouse wheel on.
 * @param {number} ticks Number of ticks to scroll the mouse wheel; a positive
 *   number scrolls down and a negative scrolls up.
 * @param {goog.math.Coordinate=} opt_coords Mouse position relative to the
 *   element.
 * @param {bot.Mouse=} opt_mouse Mouse to use; if not provided, constructs one.
 * @throws {bot.Error} If the element cannot be interacted with.
 */
bot.action.scrollMouse = function (element, ticks, opt_coords, opt_mouse) {
  var coords = bot.action.prepareToInteractWith_(element, opt_coords);
  var mouse = opt_mouse || new bot.Mouse();
  mouse.move(element, coords);
  mouse.scroll(ticks);
};


/**
 * Drags the given `element` by (dx, dy) with a virtual mouse.
 *
 * @param {!Element} element The element to drag.
 * @param {number} dx Increment in x coordinate.
 * @param {number} dy Increment in y coordinate.
 * @param {number=} opt_steps The number of steps that should occur as part of
 *     the drag, default is 2.
 * @param {goog.math.Coordinate=} opt_coords Drag start position relative to the
 *   element.
 * @param {bot.Mouse=} opt_mouse Mouse to use; if not provided, constructs one.
 * @throws {bot.Error} If the element cannot be interacted with.
 */
bot.action.drag = function (element, dx, dy, opt_steps, opt_coords, opt_mouse) {
  var coords = bot.action.prepareToInteractWith_(element, opt_coords);
  var initRect = bot.dom.getClientRect(element);
  var mouse = opt_mouse || new bot.Mouse();
  mouse.move(element, coords);
  mouse.pressButton(bot.Mouse.Button.LEFT);
  var steps = opt_steps !== undefined ? opt_steps : 2;
  if (steps < 1) {
    throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR,
      'There must be at least one step as part of a drag.');
  }
  for (var i = 1; i <= steps; i++) {
    moveTo(Math.floor(i * dx / steps), Math.floor(i * dy / steps));
  }
  mouse.releaseButton();

  function moveTo(x, y) {
    var currRect = bot.dom.getClientRect(element);
    var newPos = new goog.math.Coordinate(
      coords.x + initRect.left + x - currRect.left,
      coords.y + initRect.top + y - currRect.top);
    mouse.move(element, newPos);
  }
};


/**
 * Taps on the given `element` with a virtual touch screen.
 *
 * @param {!Element} element The element to tap.
 * @param {goog.math.Coordinate=} opt_coords Finger position relative to the
 *   target.
 * @param {bot.Touchscreen=} opt_touchscreen Touchscreen to use; if not
 *    provided, constructs one.
 * @throws {bot.Error} If the element cannot be interacted with.
 */
bot.action.tap = function (element, opt_coords, opt_touchscreen) {
  var coords = bot.action.prepareToInteractWith_(element, opt_coords);
  var touchscreen = opt_touchscreen || new bot.Touchscreen();
  touchscreen.move(element, coords);
  touchscreen.press();
  touchscreen.release();
};


/**
 * Swipes the given `element` by (dx, dy) with a virtual touch screen.
 *
 * @param {!Element} element The element to swipe.
 * @param {number} dx Increment in x coordinate.
 * @param {number} dy Increment in y coordinate.
 * @param {number=} opt_steps The number of steps that should occurs as part of
 *     the swipe, default is 2.
 * @param {goog.math.Coordinate=} opt_coords Swipe start position relative to
 *   the element.
 * @param {bot.Touchscreen=} opt_touchscreen Touchscreen to use; if not
 *    provided, constructs one.
 * @throws {bot.Error} If the element cannot be interacted with.
 */
bot.action.swipe = function (element, dx, dy, opt_steps, opt_coords,
  opt_touchscreen) {
  var coords = bot.action.prepareToInteractWith_(element, opt_coords);
  var touchscreen = opt_touchscreen || new bot.Touchscreen();
  var initRect = bot.dom.getClientRect(element);
  touchscreen.move(element, coords);
  touchscreen.press();
  var steps = opt_steps !== undefined ? opt_steps : 2;
  if (steps < 1) {
    throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR,
      'There must be at least one step as part of a swipe.');
  }
  for (var i = 1; i <= steps; i++) {
    moveTo(Math.floor(i * dx / steps), Math.floor(i * dy / steps));
  }
  touchscreen.release();

  function moveTo(x, y) {
    var currRect = bot.dom.getClientRect(element);
    var newPos = new goog.math.Coordinate(
      coords.x + initRect.left + x - currRect.left,
      coords.y + initRect.top + y - currRect.top);
    touchscreen.move(element, newPos);
  }
};


/**
 * Pinches the given `element` by the given distance with a virtual touch
 * screen. A positive distance moves two fingers inward toward each and a
 * negative distances spreads them outward. The optional coordinate is the point
 * the fingers move towards (for positive distances) or away from (for negative
 * distances); and if not provided, defaults to the center of the element.
 *
 * @param {!Element} element The element to pinch.
 * @param {number} distance The distance by which to pinch the element.
 * @param {goog.math.Coordinate=} opt_coords Position relative to the element
 *   at the center of the pinch.
 * @param {bot.Touchscreen=} opt_touchscreen Touchscreen to use; if not
 *    provided, constructs one.
 * @throws {bot.Error} If the element cannot be interacted with.
 */
bot.action.pinch = function (element, distance, opt_coords, opt_touchscreen) {
  if (distance == 0) {
    throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR,
      'Cannot pinch by a distance of zero.');
  }
  function startSoThatEndsAtMax(offsetVec) {
    if (distance < 0) {
      var magnitude = offsetVec.magnitude();
      offsetVec.scale(magnitude ? (magnitude + distance) / magnitude : 0);
    }
  }
  var halfDistance = distance / 2;
  function scaleByHalfDistance(offsetVec) {
    var magnitude = offsetVec.magnitude();
    offsetVec.scale(magnitude ? (magnitude - halfDistance) / magnitude : 0);
  }
  bot.action.multiTouchAction_(element,
    startSoThatEndsAtMax,
    scaleByHalfDistance,
    opt_coords,
    opt_touchscreen);
};


/**
 * Rotates the given `element` by the given angle with a virtual touch
 * screen. A positive angle moves two fingers clockwise and a negative angle
 * moves them counter-clockwise. The optional coordinate is the point to
 * rotate around; and if not provided, defaults to the center of the element.
 *
 * @param {!Element} element The element to rotate.
 * @param {number} angle The angle by which to rotate the element.
 * @param {goog.math.Coordinate=} opt_coords Position relative to the element
 *   at the center of the rotation.
 * @param {bot.Touchscreen=} opt_touchscreen Touchscreen to use; if not
 *    provided, constructs one.
 * @throws {bot.Error} If the element cannot be interacted with.
 */
bot.action.rotate = function (element, angle, opt_coords, opt_touchscreen) {
  if (angle == 0) {
    throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR,
      'Cannot rotate by an angle of zero.');
  }
  function startHalfwayToMax(offsetVec) {
    offsetVec.scale(0.5);
  }
  var halfRadians = Math.PI * (angle / 180) / 2;
  function rotateByHalfAngle(offsetVec) {
    offsetVec.rotate(halfRadians);
  }
  bot.action.multiTouchAction_(element,
    startHalfwayToMax,
    rotateByHalfAngle,
    opt_coords,
    opt_touchscreen);
};


/**
 * Performs a multi-touch action with two fingers on the given element. This
 * helper function works by manipulating an "offsetVector", which is the vector
 * away from the center of the interaction at which the fingers are positioned.
 * It computes the maximum offset vector and passes it to transformStart to
 * find the starting position of the fingers; it then passes it to transformHalf
 * twice to find the midpoint and final position of the fingers.
 *
 * @param {!Element} element Element to interact with.
 * @param {function(goog.math.Vec2)} transformStart Function to transform the
 *   maximum offset vector to the starting offset vector.
 * @param {function(goog.math.Vec2)} transformHalf Function to transform the
 *   offset vector halfway to its destination.
 * @param {goog.math.Coordinate=} opt_coords Position relative to the element
 *   at the center of the pinch.
 * @param {bot.Touchscreen=} opt_touchscreen Touchscreen to use; if not
 *    provided, constructs one.
 * @private
 */
bot.action.multiTouchAction_ = function (element, transformStart, transformHalf,
  opt_coords, opt_touchscreen) {
  var center = bot.action.prepareToInteractWith_(element, opt_coords);
  var size = bot.action.getInteractableSize(element);
  var offsetVec = new goog.math.Vec2(
    Math.min(center.x, size.width - center.x),
    Math.min(center.y, size.height - center.y));

  var touchScreen = opt_touchscreen || new bot.Touchscreen();
  transformStart(offsetVec);
  var start1 = goog.math.Vec2.sum(center, offsetVec);
  var start2 = goog.math.Vec2.difference(center, offsetVec);
  touchScreen.move(element, start1, start2);
  touchScreen.press(/*Two Finger Press*/ true);

  var initRect = bot.dom.getClientRect(element);
  transformHalf(offsetVec);
  var mid1 = goog.math.Vec2.sum(center, offsetVec);
  var mid2 = goog.math.Vec2.difference(center, offsetVec);
  touchScreen.move(element, mid1, mid2);

  var midRect = bot.dom.getClientRect(element);
  var movedVec = goog.math.Vec2.difference(
    new goog.math.Vec2(midRect.left, midRect.top),
    new goog.math.Vec2(initRect.left, initRect.top));
  transformHalf(offsetVec);
  var end1 = goog.math.Vec2.sum(center, offsetVec).subtract(movedVec);
  var end2 = goog.math.Vec2.difference(center, offsetVec).subtract(movedVec);
  touchScreen.move(element, end1, end2);
  touchScreen.release();
};


/**
 * Prepares to interact with the given `element`. It checks if the the
 * element is shown, scrolls the element into view, and returns the coordinates
 * of the interaction, which if not provided, is the center of the element.
 *
 * @param {!Element} element The element to be interacted with.
 * @param {goog.math.Coordinate=} opt_coords Position relative to the target.
 * @return {!goog.math.Vec2} Coordinates at the center of the interaction.
 * @throws {bot.Error} If the element cannot be interacted with.
 * @private
 */
bot.action.prepareToInteractWith_ = function (element, opt_coords) {
  bot.action.checkShown_(element);
  bot.action.scrollIntoView(element, opt_coords || undefined);

  // NOTE: Ideally, we would check that any provided coordinates fall
  // within the bounds of the element, but this has proven difficult, because:
  // (1) Browsers sometimes lie about the true size of elements, e.g. when text
  // overflows the bounding box of an element, browsers report the size of the
  // box even though the true area that can be interacted with is larger; and
  // (2) Elements with children styled as position:absolute will often not have
  // a bounding box that surrounds all of their children, but it is useful for
  // the user to be able to interact with this parent element as if it does.
  if (opt_coords) {
    return goog.math.Vec2.fromCoordinate(opt_coords);
  } else {
    var size = bot.action.getInteractableSize(element);
    return new goog.math.Vec2(size.width / 2, size.height / 2);
  }
};


/**
 * Returns the interactable size of an element.
 *
 * @param {!Element} elem Element.
 * @return {!goog.math.Size} size Size of the element.
 */
bot.action.getInteractableSize = function (elem) {
  var size = goog.style.getSize(elem);
  return ((size.width > 0 && size.height > 0) || !elem.offsetParent) ? size :
    bot.action.getInteractableSize(elem.offsetParent);
};



/**
 * A Device that is intended to allows access to protected members of the
 * Device superclass. A singleton.
 *
 * @constructor
 * @extends {bot.Device}
 * @private
 */
bot.action.LegacyDevice_ = function () {
  bot.Device.call(this);
};
goog.utils.inherits(bot.action.LegacyDevice_, bot.Device);
goog.utils.addSingletonGetter(bot.action.LegacyDevice_);


/**
 * Focuses on the given element.  See {@link bot.device.focusOnElement}.
 * @param {!Element} element The element to focus on.
 * @return {boolean} True if element.focus() was called on the element.
 */
bot.action.LegacyDevice_.focusOnElement = function (element) {
  var instance = bot.action.LegacyDevice_.getInstance();
  instance.setElement(element);
  return instance.focusOnElement();
};


/**
 * Submit the form for the element.  See {@link bot.device.submit}.
 * @param {!Element} element The element to submit a form on.
 * @param {!Element} form The form to submit.
 */
bot.action.LegacyDevice_.submitForm = function (element, form) {
  var instance = bot.action.LegacyDevice_.getInstance();
  instance.setElement(element);
  instance.submitForm(form);
};


/**
 * Find FORM element that is an ancestor of the passed in element.  See
 * {@link bot.device.findAncestorForm}.
 * @param {!Element} element The element to find an ancestor form.
 * @return {Element} form The ancestor form, or null if none.
 */
bot.action.LegacyDevice_.findAncestorForm = function (element) {
  return bot.Device.findAncestorForm(element);
};


/**
 * Scrolls the given `element` in to the current viewport. Aims to do the
 * minimum scrolling necessary, but prefers too much scrolling to too little.
 *
 * If an optional coordinate or rectangle region is provided, scrolls that
 * region relative to the element into view. A coordinate is treated as a 1x1
 * region whose top-left corner is positioned at that coordinate.
 *
 * @param {!Element} element The element to scroll in to view.
 * @param {!(goog.math.Coordinate|goog.math.Rect)=} opt_region
 *     Region relative to the top-left corner of the element.
 * @return {boolean} Whether the element is in view after scrolling.
 */
bot.action.scrollIntoView = function (element, opt_region) {
  // If the element is already in view, return true; if hidden, return false.
  var overflow = bot.dom.getOverflowState(element, opt_region);
  if (overflow != bot.dom.OverflowState.SCROLL) {
    return overflow == bot.dom.OverflowState.NONE;
  }

  // Some elements may not have a scrollIntoView function - for example,
  // elements under an SVG element. Call those only if they exist.
  if (element.scrollIntoView) {
    element.scrollIntoView();
    if (bot.dom.OverflowState.NONE ==
      bot.dom.getOverflowState(element, opt_region)) {
      return true;
    }
  }

  // There may have not been a scrollIntoView function, or the specified
  // coordinate may not be in view, so scroll "manually".
  var region = bot.dom.getClientRegion(element, opt_region);
  for (var container = bot.dom.getParentElement(element);
    container;
    container = bot.dom.getParentElement(container)) {
    scrollClientRegionIntoContainerView(container);
  }
  return bot.dom.OverflowState.NONE ==
    bot.dom.getOverflowState(element, opt_region);

  function scrollClientRegionIntoContainerView(container) {
    // Based largely from goog.style.scrollIntoContainerView.
    var containerRect = bot.dom.getClientRect(container);
    var containerBorder = goog.style.getBorderBox(container);

    // Relative position of the region to the container's content box.
    var relX = region.left - containerRect.left - containerBorder.left;
    var relY = region.top - containerRect.top - containerBorder.top;

    // How much the region can move in the container. Use the container's
    // clientWidth/Height, not containerRect, to account for the scrollbar.
    var spaceX = container.clientWidth + region.left - region.right;
    var spaceY = container.clientHeight + region.top - region.bottom;

    // Scroll the element into view of the container.
    container.scrollLeft += Math.min(relX, Math.max(relX - spaceX, 0));
    container.scrollTop += Math.min(relY, Math.max(relY - spaceY, 0));
  }
};
