// 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 browser window.
 */

goog.provide('bot.window');

goog.require('bot');
goog.require('bot.Error');
goog.require('bot.ErrorCode');
goog.require('bot.events');
goog.require('bot.userAgent');
goog.require('goog.dom');
goog.require('goog.dom.DomHelper');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Size');
goog.require('goog.style');
goog.require('goog.userAgent');
goog.require('goog.userAgent.product');


/**
 * Whether the value of history.length includes a newly loaded page. If not,
 * after a new page load history.length is the number of pages that have loaded,
 * minus 1, but becomes the total number of pages on a subsequent back() call.
 * @private {boolean}
 * @const
 */
bot.window.HISTORY_LENGTH_INCLUDES_NEW_PAGE_ = !goog.userAgent.IE;


/**
 * Whether value of history.length includes the pages ahead of the current one
 * in the history. If not, history.length equals the number of prior pages.
 * Here is the WebKit bug for this behavior that was fixed by version 533:
 * https://bugs.webkit.org/show_bug.cgi?id=24472
 * @private {boolean}
 * @const
 */
bot.window.HISTORY_LENGTH_INCLUDES_FORWARD_PAGES_ =
  !goog.userAgent.WEBKIT || bot.userAgent.isEngineVersion('533');


/**
 * Screen orientation values. From the draft W3C spec at:
 * http://www.w3.org/TR/2012/WD-screen-orientation-20120522
 *
 * @enum {string}
 */
bot.window.Orientation = {
  PORTRAIT: 'portrait-primary',
  PORTRAIT_SECONDARY: 'portrait-secondary',
  LANDSCAPE: 'landscape-primary',
  LANDSCAPE_SECONDARY: 'landscape-secondary'
};


/**
 * Returns the degrees corresponding to the orientation input.
 *
 * @param {!bot.window.Orientation} orientation The orientation.
 * @return {number} The orientation degrees.
 * @private
 */
bot.window.getOrientationDegrees_ = (function () {
  var orientationMap;
  return function (orientation) {
    if (!orientationMap) {
      orientationMap = {};
      if (goog.userAgent.MOBILE) {
        // The iPhone and Android phones do not change orientation event when
        // held upside down. Hence, PORTRAIT_SECONDARY is not set.
        orientationMap[bot.window.Orientation.PORTRAIT] = 0;
        orientationMap[bot.window.Orientation.LANDSCAPE] = 90;
        orientationMap[bot.window.Orientation.LANDSCAPE_SECONDARY] = -90;
        if (goog.userAgent.product.IPAD) {
          orientationMap[bot.window.Orientation.PORTRAIT_SECONDARY] = 180;
        }
      } else if (goog.userAgent.product.ANDROID) {
        // Unlike the iPad, Android tablets treat landscape orientation as the
        // default, i.e., having window.orientation = 0.
        orientationMap[bot.window.Orientation.PORTRAIT] = -90;
        orientationMap[bot.window.Orientation.LANDSCAPE] = 0;
        orientationMap[bot.window.Orientation.PORTRAIT_SECONDARY] = 90;
        orientationMap[bot.window.Orientation.LANDSCAPE_SECONDARY] = 180;
      }
    }
    return orientationMap[orientation];
  };
})();


/**
 * Go back in the browser history. The number of pages to go back can
 * optionally be specified and defaults to 1.
 *
 * @param {number=} opt_numPages Number of pages to go back.
 */
bot.window.back = function (opt_numPages) {
  // Relax the upper bound by one for browsers that do not count
  // newly loaded pages towards the value of window.history.length.
  var maxPages = bot.window.HISTORY_LENGTH_INCLUDES_NEW_PAGE_ ?
    bot.getWindow().history.length - 1 : bot.getWindow().history.length;
  var numPages = bot.window.checkNumPages_(maxPages, opt_numPages);
  bot.getWindow().history.go(-numPages);
};


/**
 * Go forward in the browser history. The number of pages to go forward can
 * optionally be specified and defaults to 1.
 *
 * @param {number=} opt_numPages Number of pages to go forward.
 */
bot.window.forward = function (opt_numPages) {
  // Do not check the upper bound (use null for infinity) for browsers that
  // do not count forward pages towards the value of window.history.length.
  var maxPages = bot.window.HISTORY_LENGTH_INCLUDES_FORWARD_PAGES_ ?
    bot.getWindow().history.length - 1 : null;
  var numPages = bot.window.checkNumPages_(maxPages, opt_numPages);
  bot.getWindow().history.go(numPages);
};


/**
 * @param {?number} maxPages Upper bound on number of pages; null for infinity.
 * @param {number=} opt_numPages Number of pages to move in history.
 * @return {number} Correct number of pages to move in history.
 * @private
 */
bot.window.checkNumPages_ = function (maxPages, opt_numPages) {
  var numPages = opt_numPages !== undefined ? opt_numPages : 1;
  if (numPages <= 0) {
    throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR,
      'number of pages must be positive');
  }
  if (maxPages !== null && numPages > maxPages) {
    throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR,
      'number of pages must be less than the length of the browser history');
  }
  return numPages;
};


/**
 * Determine the size of the window that a user could interact with. This will
 * be the greatest of document.body.(width|scrollWidth), the same for
 * document.documentElement or the size of the viewport.
 *
 * @param {!Window=} opt_win Window to determine the size of. Defaults to
 *   bot.getWindow().
 * @return {!goog.math.Size} The calculated size.
 */
bot.window.getInteractableSize = function (opt_win) {
  var win = opt_win || bot.getWindow();
  var doc = win.document;
  var elem = doc.documentElement;
  var body = doc.body;
  if (!body) {
    throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR,
      'No BODY element present');
  }

  var widths = [
    elem.clientWidth, elem.scrollWidth, elem.offsetWidth,
    body.scrollWidth, body.offsetWidth
  ];
  var heights = [
    elem.clientHeight, elem.scrollHeight, elem.offsetHeight,
    body.scrollHeight, body.offsetHeight
  ];

  var width = Math.max.apply(null, widths);
  var height = Math.max.apply(null, heights);

  return new goog.math.Size(width, height);
};


/**
 * Gets the frame element.
 *
 * @param {!Window} win Window of the frame. Defaults to bot.getWindow().
 * @return {Element} The frame element if it exists, null otherwise.
 * @private
 */
bot.window.getFrame_ = function (win) {
  try {
    // On IE, accessing the frameElement of a popup window results in a "No
    // Such interface" exception.
    return win.frameElement;
  } catch (e) {
    return null;
  }
};


/**
 * Determine the outer size of the window.
 *
 * @param {!Window=} opt_win Window to determine the size of. Defaults to
 *   bot.getWindow().
 * @return {!goog.math.Size} The calculated size.
 */
bot.window.getSize = function (opt_win) {
  var win = opt_win || bot.getWindow();
  var frame = bot.window.getFrame_(win);
  if (bot.userAgent.ANDROID_PRE_ICECREAMSANDWICH) {
    if (frame) {
      // Early Android browsers do not account for border width.
      var box = goog.style.getBorderBox(frame);
      return new goog.math.Size(frame.clientWidth - box.left - box.right,
        frame.clientHeight);
    } else {
      // A fixed popup size.
      return new goog.math.Size(320, 240);
    }
  } else if (frame) {
    return new goog.math.Size(frame.clientWidth, frame.clientHeight);
  } else {
    var docElem = win.document.documentElement;
    var body = win.document.body;
    var width = win.outerWidth || (docElem && docElem.clientWidth) ||
      (body && body.clientWidth) || 0;
    var height = win.outerHeight || (docElem && docElem.clientHeight) ||
      (body && body.clientHeight) || 0;
    return new goog.math.Size(width, height);
  }
};


/**
 * Set the outer size of the window.
 *
 * @param {!goog.math.Size} size The new window size.
 * @param {!Window=} opt_win Window to determine the size of. Defaults to
 *   bot.getWindow().
 */
bot.window.setSize = function (size, opt_win) {
  var win = opt_win || bot.getWindow();
  var frame = bot.window.getFrame_(win);
  if (frame) {
    // minHeight and minWidth are altered because many browsers will not change
    // height or width if it is less than a specified minHeight or minWidth.
    frame.style.minHeight = '0px';
    frame.style.minWidth = '0px';
    frame.width = size.width + 'px';
    frame.style.width = size.width + 'px';
    frame.height = size.height + 'px';
    frame.style.height = size.height + 'px';
  } else {
    win.resizeTo(size.width, size.height);
  }
};


/**
 * Determine the scroll position of the window.
 *
 * @param {!Window=} opt_win Window to determine the scroll position of.
 *   Defaults to bot.getWindow().
 * @return {!goog.math.Coordinate} The scroll position.
 */
bot.window.getScroll = function (opt_win) {
  var win = opt_win || bot.getWindow();
  return new goog.dom.DomHelper(win.document).getDocumentScroll();
};


/**
 * Set the scroll position of the window.
 *
 * @param {!goog.math.Coordinate} position The new scroll position.
 * @param {!Window=} opt_win Window to apply position to. Defaults to
 *   bot.getWindow().
 */
bot.window.setScroll = function (position, opt_win) {
  var win = opt_win || bot.getWindow();
  win.scrollTo(position.x, position.y);
};


/**
 * Get the position of the window.
 *
 * @param {!Window=} opt_win Window to determine the position of. Defaults to
 *   bot.getWindow().
 * @return {!goog.math.Coordinate} The position of the window.
 */
bot.window.getPosition = function (opt_win) {
  var win = opt_win || bot.getWindow();
  var x, y;

  if (goog.userAgent.IE) {
    x = win.screenLeft;
    y = win.screenTop;
  } else {
    x = win.screenX;
    y = win.screenY;
  }

  return new goog.math.Coordinate(x, y);
};


/**
 * Set the position of the window.
 *
 * @param {!goog.math.Coordinate} position The target position.
 * @param {!Window=} opt_win Window to set the position of. Defaults to
 *   bot.getWindow().
 */
bot.window.setPosition = function (position, opt_win) {
  var win = opt_win || bot.getWindow();
  win.moveTo(position.x, position.y);
};


/**
 * Scrolls the given position into the viewport, using the minimal amount of
 * scrolling necessary to being the coordinate into view.
 *
 * @param {!goog.math.Coordinate} position The position to scroll into view.
 * @param {!Window=} opt_win Window to apply position to. Defaults to
 *   bot.getWindow().
 */
bot.window.scrollIntoView = function (position, opt_win) {
  var win = opt_win || bot.getWindow();
  var viewport = goog.dom.getViewportSize(win);
  var scroll = bot.window.getScroll(win);

  // Scroll the minimal amount to bring the position into view.
  var targetScroll = new goog.math.Coordinate(
    newScrollDim(position.x, scroll.x, viewport.width),
    newScrollDim(position.y, scroll.y, viewport.height));
  if (!goog.math.Coordinate.equals(targetScroll, scroll)) {
    bot.window.setScroll(targetScroll, win);
  }

  // It is difficult to determine the size of the web page in some browsers.
  // We check if the scrolling we intended to do really happened. If not we
  // assume that the target location is not on the web page.
  if (!goog.math.Coordinate.equals(targetScroll, bot.window.getScroll(win))) {
    throw new bot.Error(bot.ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS,
      'The target scroll location ' + targetScroll + ' is not on the page.');
  }

  function newScrollDim(positionDim, scrollDim, viewportDim) {
    if (positionDim < scrollDim) {
      return positionDim;
    } else if (positionDim >= scrollDim + viewportDim) {
      return positionDim - viewportDim + 1;
    } else {
      return scrollDim;
    }
  }
};


/**
 * @return {number} The current window orientation degrees.
 *     window.
 * @private
 */
bot.window.getCurrentOrientationDegrees_ = function () {
  var win = bot.getWindow();
  if (win.orientation === undefined) {
    // If window.orientation is not defined, assume a default orientation of 0.
    // A value of 0 indicates a portrait orientation except for android tablets
    // where 0 indicates a landscape orientation.
    win.orientation = 0;
  }
  return win.orientation;
};


/**
 * Changes window orientation.
 *
 * @param {!bot.window.Orientation} orientation The new orientation of the
 *     window.
 */
bot.window.changeOrientation = function (orientation) {
  var win = bot.getWindow();
  var currentOrientationDegrees = bot.window.getCurrentOrientationDegrees_();
  var newOrientationDegrees = bot.window.getOrientationDegrees_(orientation);
  if (currentOrientationDegrees == newOrientationDegrees ||
    newOrientationDegrees === undefined) {
    return;
  }

  // If possible, try to override the window's orientation value.
  // On some older version of Android, it's not possible to change
  // the window's orientation value.
  if (Object.getOwnPropertyDescriptor && Object.defineProperty) {
    var descriptor = Object.getOwnPropertyDescriptor(win, 'orientation');
    if (descriptor && descriptor.configurable) {
      Object.defineProperty(win, 'orientation', {
        configurable: true,
        get: function () {
          return newOrientationDegrees;
        }
      });
    }
  }
  bot.events.fire(win, bot.events.EventType.ORIENTATIONCHANGE);

  // Change the window size to reflect the new orientation.
  if (Math.abs(currentOrientationDegrees - newOrientationDegrees) % 180 != 0) {
    var size = bot.window.getSize();
    var shorter = size.getShortest();
    var longer = size.getLongest();
    if (orientation == bot.window.Orientation.PORTRAIT ||
      orientation == bot.window.Orientation.PORTRAIT_SECONDARY) {
      bot.window.setSize(new goog.math.Size(shorter, longer));
    } else {
      bot.window.setSize(new goog.math.Size(longer, shorter));
    }
  }
};
