// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('ntp', function() {
  'use strict';

  // We can't pass the currently dragging tile via dataTransfer because of
  // http://crbug.com/31037
  var currentlyDraggingTile = null;
  function getCurrentlyDraggingTile() {
    return currentlyDraggingTile;
  }
  function setCurrentlyDraggingTile(tile) {
    currentlyDraggingTile = tile;
    if (tile)
      ntp.enterRearrangeMode();
    else
      ntp.leaveRearrangeMode();
  }

  /**
   * Changes the current dropEffect of a drag. This modifies the native cursor
   * and serves as an indicator of what we should do at the end of the drag as
   * well as give indication to the user if a drop would succeed if they let go.
   * @param {DataTransfer} dataTransfer A dataTransfer object from a drag event.
   * @param {string} effect A drop effect to change to (i.e. copy, move, none).
   */
  function setCurrentDropEffect(dataTransfer, effect) {
    dataTransfer.dropEffect = effect;
    if (currentlyDraggingTile)
      currentlyDraggingTile.lastDropEffect = dataTransfer.dropEffect;
  }

  /**
   * Creates a new Tile object. Tiles wrap content on a TilePage, providing
   * some styling and drag functionality.
   * @constructor
   * @extends {HTMLDivElement}
   */
  function Tile(contents) {
    var tile = cr.doc.createElement('div');
    tile.__proto__ = Tile.prototype;
    tile.initialize(contents);

    return tile;
  }

  Tile.prototype = {
    __proto__: HTMLDivElement.prototype,

    initialize: function(contents) {
      // 'real' as opposed to doppleganger.
      this.className = 'tile real';
      this.appendChild(contents);
      contents.tile = this;

      this.addEventListener('dragstart', this.onDragStart_);
      this.addEventListener('drag', this.onDragMove_);
      this.addEventListener('dragend', this.onDragEnd_);

      this.firstChild.addEventListener(
          'webkitAnimationEnd', this.onContentsAnimationEnd_.bind(this));

      this.eventTracker = new EventTracker();
    },

    get index() {
      return Array.prototype.indexOf.call(this.tilePage.tileElements_, this);
    },

    get tilePage() {
      return findAncestorByClass(this, 'tile-page');
    },

    /**
     * Position the tile at |x, y|, and store this as the grid location, i.e.
     * where the tile 'belongs' when it's not being dragged.
     * @param {number} x The x coordinate, in pixels.
     * @param {number} y The y coordinate, in pixels.
     */
    setGridPosition: function(x, y) {
      this.gridX = x;
      this.gridY = y;
      this.moveTo(x, y);
    },

    /**
     * Position the tile at |x, y|.
     * @param {number} x The x coordinate, in pixels.
     * @param {number} y The y coordinate, in pixels.
     */
    moveTo: function(x, y) {
      // left overrides right in LTR, and right takes precedence in RTL.
      this.style.left = toCssPx(x);
      this.style.right = toCssPx(x);
      this.style.top = toCssPx(y);
    },

    /**
     * The handler for dragstart events fired on |this|.
     * @param {Event} e The event for the drag.
     * @private
     */
    onDragStart_: function(e) {
      // The user may start dragging again during a previous drag's finishing
      // animation.
      if (this.classList.contains('dragging'))
        this.finalizeDrag_();

      setCurrentlyDraggingTile(this);

      e.dataTransfer.effectAllowed = 'copyMove';
      this.firstChild.setDragData(e.dataTransfer);

      // The drag clone is the node we use as a representation during the drag.
      // It's attached to the top level document element so that it floats above
      // image masks.
      this.dragClone = this.cloneNode(true);
      this.dragClone.style.right = '';
      this.dragClone.classList.add('drag-representation');
      $('card-slider-frame').appendChild(this.dragClone);
      this.eventTracker.add(this.dragClone, 'webkitTransitionEnd',
                            this.onDragCloneTransitionEnd_.bind(this));

      this.classList.add('dragging');
      // offsetLeft is mirrored in RTL. Un-mirror it.
      var offsetLeft = isRTL() ?
          this.parentNode.clientWidth - this.offsetLeft :
          this.offsetLeft;
      this.dragOffsetX = e.x - offsetLeft - this.parentNode.offsetLeft;
      this.dragOffsetY = e.y - this.offsetTop -
          // Unlike offsetTop, this value takes scroll position into account.
          this.parentNode.getBoundingClientRect().top;

      this.onDragMove_(e);
    },

    /**
     * The handler for drag events fired on |this|.
     * @param {Event} e The event for the drag.
     * @private
     */
    onDragMove_: function(e) {
      if (e.view != window || (e.x == 0 && e.y == 0)) {
        this.dragClone.hidden = true;
        return;
      }

      this.dragClone.hidden = false;
      this.dragClone.style.left = toCssPx(e.x - this.dragOffsetX);
      this.dragClone.style.top = toCssPx(e.y - this.dragOffsetY);
    },

    /**
     * The handler for dragend events fired on |this|.
     * @param {Event} e The event for the drag.
     * @private
     */
    onDragEnd_: function(e) {
      this.dragClone.hidden = false;
      this.dragClone.classList.add('placing');

      setCurrentlyDraggingTile(null);

      // tilePage will be null if we've already been removed.
      var tilePage = this.tilePage;
      if (tilePage)
        tilePage.positionTile_(this.index);

      // Take an appropriate action with the drag clone.
      if (this.landedOnTrash) {
        this.dragClone.classList.add('deleting');
      } else if (tilePage) {
        // TODO(dbeam): Until we fix dropEffect to the correct behavior it will
        // differ on windows - crbug.com/39399.  That's why we use the custom
        // this.lastDropEffect instead of e.dataTransfer.dropEffect.
        if (tilePage.selected && this.lastDropEffect != 'copy') {
          // The drag clone can still be hidden from the last drag move event.
          this.dragClone.hidden = false;
          // The tile's contents may have moved following the respositioning;
          // adjust for that.
          var contentDiffX = this.dragClone.firstChild.offsetLeft -
              this.firstChild.offsetLeft;
          var contentDiffY = this.dragClone.firstChild.offsetTop -
              this.firstChild.offsetTop;
          this.dragClone.style.left =
              toCssPx(this.gridX + this.parentNode.offsetLeft -
                         contentDiffX);
          this.dragClone.style.top =
              toCssPx(this.gridY +
                         this.parentNode.getBoundingClientRect().top -
                         contentDiffY);
        } else if (this.dragClone.hidden) {
          this.finalizeDrag_();
        } else {
          // The CSS3 transitions spec intentionally leaves it up to individual
          // user agents to determine when styles should be applied. On some
          // platforms (at the moment, Windows), when you apply both classes
          // immediately a transition may not occur correctly. That's why we're
          // using a setTimeout here to queue adding the class until the
          // previous class (currently: .placing) sets up a transition.
          // http://dev.w3.org/csswg/css3-transitions/#starting
          window.setTimeout(function() {
            if (this.dragClone)
              this.dragClone.classList.add('dropped-on-other-page');
          }.bind(this), 0);
        }
      }

      delete this.lastDropEffect;
      this.landedOnTrash = false;
    },

    /**
     * Creates a clone of this node offset by the coordinates. Used for the
     * dragging effect where a tile appears to float off one side of the grid
     * and re-appear on the other.
     * @param {number} x x-axis offset, in pixels.
     * @param {number} y y-axis offset, in pixels.
     */
    showDoppleganger: function(x, y) {
      // We always have to clear the previous doppleganger to make sure we get
      // style updates for the contents of this tile.
      this.clearDoppleganger();

      var clone = this.cloneNode(true);
      clone.classList.remove('real');
      clone.classList.add('doppleganger');
      var clonelets = clone.querySelectorAll('.real');
      for (var i = 0; i < clonelets.length; i++) {
        clonelets[i].classList.remove('real');
      }

      this.appendChild(clone);
      this.doppleganger_ = clone;

      if (isRTL())
        x *= -1;

      this.doppleganger_.style.WebkitTransform = 'translate(' + x + 'px, ' +
                                                                y + 'px)';
    },

    /**
     * Destroys the current doppleganger.
     */
    clearDoppleganger: function() {
      if (this.doppleganger_) {
        this.removeChild(this.doppleganger_);
        this.doppleganger_ = null;
      }
    },

    /**
     * Returns status of doppleganger.
     * @return {boolean} True if there is a doppleganger showing for |this|.
     */
    hasDoppleganger: function() {
      return !!this.doppleganger_;
    },

    /**
     * Cleans up after the drag is over. This is either called when the
     * drag representation finishes animating to the final position, or when
     * the next drag starts (if the user starts a 2nd drag very quickly).
     * @private
     */
    finalizeDrag_: function() {
      assert(this.classList.contains('dragging'));

      var clone = this.dragClone;
      this.dragClone = null;

      clone.parentNode.removeChild(clone);
      this.eventTracker.remove(clone, 'webkitTransitionEnd');
      this.classList.remove('dragging');
      if (this.firstChild.finalizeDrag)
        this.firstChild.finalizeDrag();
    },

    /**
     * Called when the drag representation node is done migrating to its final
     * resting spot.
     * @param {Event} e The transition end event.
     */
    onDragCloneTransitionEnd_: function(e) {
      if (this.classList.contains('dragging') &&
          (e.propertyName == 'left' || e.propertyName == 'top' ||
           e.propertyName == 'transform')) {
        this.finalizeDrag_();
      }
    },

    /**
     * Called when an app is removed from Chrome. Animates its disappearance.
     * @param {boolean=} opt_animate Whether the animation should be animated.
     */
    doRemove: function(opt_animate) {
      if (opt_animate)
        this.firstChild.classList.add('removing-tile-contents');
      else
        this.tilePage.removeTile(this, false);
    },

    /**
     * Callback for the webkitAnimationEnd event on the tile's contents.
     * @param {Event} e The event object.
     */
    onContentsAnimationEnd_: function(e) {
      if (this.firstChild.classList.contains('new-tile-contents'))
        this.firstChild.classList.remove('new-tile-contents');
      if (this.firstChild.classList.contains('removing-tile-contents'))
        this.tilePage.removeTile(this, true);
    },
  };

  /**
   * Gives the proportion of the row width that is devoted to a single icon.
   * @param {number} rowTileCount The number of tiles in a row.
   * @param {number} tileSpacingFraction The proportion of the tile width which
   *     will be used as spacing between tiles.
   * @return {number} The ratio between icon width and row width.
   */
  function tileWidthFraction(rowTileCount, tileSpacingFraction) {
    return rowTileCount + (rowTileCount - 1) * tileSpacingFraction;
  }

  /**
   * Calculates an assortment of tile-related values for a grid with the
   * given dimensions.
   * @param {number} width The pixel width of the grid.
   * @param {number} numRowTiles The number of tiles in a row.
   * @param {number} tileSpacingFraction The proportion of the tile width which
   *     will be used as spacing between tiles.
   * @return {Object} A mapping of pixel values.
   */
  function tileValuesForGrid(width, numRowTiles, tileSpacingFraction) {
    var tileWidth = width / tileWidthFraction(numRowTiles, tileSpacingFraction);
    var offsetX = tileWidth * (1 + tileSpacingFraction);
    var interTileSpacing = offsetX - tileWidth;

    return {
      tileWidth: tileWidth,
      offsetX: offsetX,
      interTileSpacing: interTileSpacing,
    };
  }

  // The smallest amount of horizontal blank space to display on the sides when
  // displaying a wide arrangement. There is an additional 26px of margin from
  // the tile page padding.
  var MIN_WIDE_MARGIN = 18;

  /**
   * Creates a new TilePage object. This object contains tiles and controls
   * their layout.
   * @param {Object} gridValues Pixel values that define the size and layout
   *     of the tile grid.
   * @constructor
   * @extends {HTMLDivElement}
   */
  function TilePage(gridValues) {
    var el = cr.doc.createElement('div');
    el.gridValues_ = gridValues;
    el.__proto__ = TilePage.prototype;
    el.initialize();

    return el;
  }

  /**
   * Takes a collection of grid layout pixel values and updates them with
   * additional tiling values that are calculated from TilePage constants.
   * @param {Object} grid The grid layout pixel values to update.
   */
  TilePage.initGridValues = function(grid) {
    // The amount of space we need to display a narrow grid (all narrow grids
    // are this size).
    grid.narrowWidth =
        grid.minTileWidth * tileWidthFraction(grid.minColCount,
                                              grid.tileSpacingFraction);
    // The minimum amount of space we need to display a wide grid.
    grid.minWideWidth =
        grid.minTileWidth * tileWidthFraction(grid.maxColCount,
                                              grid.tileSpacingFraction);
    // The largest we will ever display a wide grid.
    grid.maxWideWidth =
        grid.maxTileWidth * tileWidthFraction(grid.maxColCount,
                                              grid.tileSpacingFraction);
    // Tile-related pixel values for the narrow display.
    grid.narrowTileValues = tileValuesForGrid(grid.narrowWidth,
                                              grid.minColCount,
                                              grid.tileSpacingFraction);
    // Tile-related pixel values for the minimum narrow display.
    grid.wideTileValues = tileValuesForGrid(grid.minWideWidth,
                                            grid.maxColCount,
                                            grid.tileSpacingFraction);
  };

  TilePage.prototype = {
    __proto__: HTMLDivElement.prototype,

    initialize: function() {
      this.className = 'tile-page';

      // Div that acts as a custom scrollbar. The scrollbar has to live
      // outside the content div so it doesn't flicker when scrolling (due to
      // repainting after the scroll, then repainting again when moved in the
      // onScroll handler). |scrollbar_| is only aesthetic, and it only
      // represents the thumb. Actual events are still handled by the invisible
      // native scrollbars. This div gives us more flexibility with the visuals.
      this.scrollbar_ = this.ownerDocument.createElement('div');
      this.scrollbar_.className = 'tile-page-scrollbar';
      this.scrollbar_.hidden = true;
      this.appendChild(this.scrollbar_);

      // This contains everything but the scrollbar.
      this.content_ = this.ownerDocument.createElement('div');
      this.content_.className = 'tile-page-content';
      this.appendChild(this.content_);

      // Div that sets the vertical position of the tile grid.
      this.topMargin_ = this.ownerDocument.createElement('div');
      this.topMargin_.className = 'top-margin';
      this.content_.appendChild(this.topMargin_);

      // Div that holds the tiles.
      this.tileGrid_ = this.ownerDocument.createElement('div');
      this.tileGrid_.className = 'tile-grid';
      this.tileGrid_.style.minWidth = this.gridValues_.narrowWidth + 'px';
      this.tileGrid_.setAttribute('role', 'menu');
      this.tileGrid_.setAttribute('aria-label',
          loadTimeData.getString(
              'tile_grid_screenreader_accessible_description'));

      this.content_.appendChild(this.tileGrid_);

      // Ordered list of our tiles.
      this.tileElements_ = this.tileGrid_.getElementsByClassName('tile real');
      // Ordered list of the elements which want to accept keyboard focus. These
      // elements will not be a part of the normal tab order; the tile grid
      // initially gets focused and then these elements can be focused via the
      // arrow keys.
      this.focusableElements_ =
          this.tileGrid_.getElementsByClassName('focusable');

      // These are properties used in updateTopMargin.
      this.animatedTopMarginPx_ = 0;
      this.topMarginPx_ = 0;

      this.eventTracker = new EventTracker();
      this.eventTracker.add(window, 'resize', this.onResize_.bind(this));

      this.addEventListener('DOMNodeInsertedIntoDocument',
                            this.onNodeInsertedIntoDocument_);

      this.content_.addEventListener('scroll', this.onScroll_.bind(this));

      this.dragWrapper_ = new cr.ui.DragWrapper(this.tileGrid_, this);

      this.addEventListener('cardselected', this.handleCardSelection_);
      this.addEventListener('carddeselected', this.handleCardDeselection_);
      this.addEventListener('focus', this.handleFocus_);
      this.addEventListener('keydown', this.handleKeyDown_);
      this.addEventListener('mousedown', this.handleMouseDown_);

      this.focusElementIndex_ = -1;
    },

    get tiles() {
      return this.tileElements_;
    },

    get tileCount() {
      return this.tileElements_.length;
    },

    get selected() {
      return Array.prototype.indexOf.call(this.parentNode.children, this) ==
          ntp.getCardSlider().currentCard;
    },

    /**
     * The size of the margin (unused space) on the sides of the tile grid, in
     * pixels.
     * @type {number}
     */
    get sideMargin() {
      return this.layoutValues_.leftMargin;
    },

    /**
     * Returns the width of the scrollbar, in pixels, if it is active, or 0
     * otherwise.
     * @type {number}
     */
    get scrollbarWidth() {
      return this.scrollbar_.hidden ? 0 : 13;
    },

    /**
     * Fetches the size, in pixels, of the padding-top of the tile contents.
     * @type {number}
     */
    get contentPadding() {
      if (typeof this.contentPadding_ == 'undefined') {
        this.contentPadding_ =
            parseInt(window.getComputedStyle(this.content_).paddingTop, 10);
      }
      return this.contentPadding_;
    },

    /**
     * Removes the tilePage from the DOM and cleans up event handlers.
     *
     * TODO(dbeam): this method now conflicts with HTMLElement#remove(). Rename.
     */
    remove: function() {
      // This checks arguments.length as most remove functions have a boolean
      // |opt_animate| argument, but that's not necesarilly applicable to
      // removing a tilePage. Selecting a different card in an animated way and
      // deleting the card afterward is probably a better choice.
      assert(typeof arguments[0] != 'boolean',
             'This function takes no |opt_animate| argument.');
      this.tearDown_();
      this.parentNode.removeChild(this);
    },

    /**
     * Cleans up resources that are no longer needed after this TilePage
     * instance is removed from the DOM.
     * @private
     */
    tearDown_: function() {
      this.eventTracker.removeAll();
    },

    /**
     * Appends a tile to the end of the tile grid.
     * @param {HTMLElement} tileElement The contents of the tile.
     * @param {boolean} animate If true, the append will be animated.
     * @protected
     */
    appendTile: function(tileElement, animate) {
      this.addTileAt(tileElement, this.tileElements_.length, animate);
    },

    /**
     * Adds the given element to the tile grid.
     * @param {Node} tileElement The tile object/node to insert.
     * @param {number} index The location in the tile grid to insert it at.
     * @param {boolean} animate If true, the tile in question will be
     *     animated (other tiles, if they must reposition, do not animate).
     * @protected
     */
    addTileAt: function(tileElement, index, animate) {
      this.classList.remove('animating-tile-page');
      if (animate)
        tileElement.classList.add('new-tile-contents');

      // Make sure the index is positive and either in the the bounds of
      // this.tileElements_ or at the end (meaning append).
      assert(index >= 0 && index <= this.tileElements_.length);

      var wrapperDiv = new Tile(tileElement);
      // If is out of the bounds of the tile element list, .insertBefore() will
      // act just like appendChild().
      this.tileGrid_.insertBefore(wrapperDiv, this.tileElements_[index]);
      this.calculateLayoutValues_();
      this.heightChanged_();

      this.repositionTiles_();

      // If this is the first tile being added, make it focusable after add.
      if (this.focusableElements_.length == 1)
        this.updateFocusableElement();
      this.fireAddedEvent(wrapperDiv, index, animate);
    },

    /**
     * Notify interested subscribers that a tile has been removed from this
     * page.
     * @param {ntp.Tile} tile The newly added tile.
     * @param {number} index The index of the tile that was added.
     * @param {boolean} wasAnimated Whether the removal was animated.
     */
    fireAddedEvent: function(tile, index, wasAnimated) {
      var e = document.createEvent('Event');
      e.initEvent('tilePage:tile_added', true, true);
      e.addedIndex = index;
      e.addedTile = tile;
      e.wasAnimated = wasAnimated;
      this.dispatchEvent(e);
    },

    /**
     * Removes the given tile and animates the repositioning of the other tiles.
     * @param {boolean=} opt_animate Whether the removal should be animated.
     * @param {boolean=} opt_dontNotify Whether a page should be removed if the
     *     last tile is removed from it.
     */
    removeTile: function(tile, opt_animate, opt_dontNotify) {
      if (opt_animate)
        this.classList.add('animating-tile-page');

      var index = tile.index;
      tile.parentNode.removeChild(tile);
      this.calculateLayoutValues_();
      this.cleanupDrag();
      this.updateFocusableElement();

      if (!opt_dontNotify)
        this.fireRemovedEvent(tile, index, !!opt_animate);
    },

    /**
     * Notify interested subscribers that a tile has been removed from this
     * page.
     * @param {ntp.Tile} tile The tile that was removed.
     * @param {number} oldIndex Where the tile was positioned before removal.
     * @param {boolean} wasAnimated Whether the removal was animated.
     */
    fireRemovedEvent: function(tile, oldIndex, wasAnimated) {
      var e = document.createEvent('Event');
      e.initEvent('tilePage:tile_removed', true, true);
      e.removedIndex = oldIndex;
      e.removedTile = tile;
      e.wasAnimated = wasAnimated;
      this.dispatchEvent(e);
    },

    /**
     * Removes all tiles from the page.
     */
    removeAllTiles: function() {
      this.tileGrid_.innerHTML = '';
    },

    /**
     * Called when the page is selected (in the card selector).
     * @param {Event} e A custom cardselected event.
     * @private
     */
    handleCardSelection_: function(e) {
      this.updateFocusableElement();

      // When we are selected, we re-calculate the layout values. (See comment
      // in doDrop.)
      this.calculateLayoutValues_();
    },

    /**
     * Called when the page loses selection (in the card selector).
     * @param {Event} e A custom carddeselected event.
     * @private
     */
    handleCardDeselection_: function(e) {
      if (this.currentFocusElement_)
        this.currentFocusElement_.tabIndex = -1;
    },

    /**
     * When we get focus, pass it on to the focus element.
     * @param {Event} e The focus event.
     * @private
     */
    handleFocus_: function(e) {
      if (this.focusableElements_.length == 0)
        return;

      this.updateFocusElement_();
    },

    /**
     * Since we are doing custom focus handling, we have to manually
     * set focusability on click (as well as keyboard nav above).
     * @param {Event} e The focus event.
     * @private
     */
    handleMouseDown_: function(e) {
      var focusable = findAncestorByClass(/** @type {Element} */(e.target),
                                          'focusable');
      if (focusable) {
        this.focusElementIndex_ =
            Array.prototype.indexOf.call(this.focusableElements_,
                                         focusable);
        this.updateFocusElement_();
      }
  },

    /**
     * Handle arrow key focus nav.
     * @param {Event} e The focus event.
     * @private
     */
    handleKeyDown_: function(e) {
      // We only handle up, down, left, right without control keys.
      if (e.metaKey || e.shiftKey || e.altKey || e.ctrlKey)
        return;

      // Wrap the given index to |this.focusableElements_|.
      var wrap = function(idx) {
        return (idx + this.focusableElements_.length) %
            this.focusableElements_.length;
      }.bind(this);

      switch (e.key) {
        case 'ArrowRight':
        case 'ArrowLeft':
          var direction = e.key == 'ArrowRight' ? 1 : -1;
          this.focusElementIndex_ = wrap(this.focusElementIndex_ + direction);
          break;
        case 'ArrowUp':
        case 'ArrowDown':
          // Look through all focusable elements. Find the first one that is
          // in the same column.
          var direction = e.key == 'ArrowUp' ? -1 : 1;
          var currentIndex =
              Array.prototype.indexOf.call(this.focusableElements_,
                                           this.currentFocusElement_);
          var newFocusIdx = wrap(currentIndex + direction);
          var tile = this.currentFocusElement_.parentNode;
          for (;; newFocusIdx = wrap(newFocusIdx + direction)) {
            var newTile = this.focusableElements_[newFocusIdx].parentNode;
            var rowTiles = this.layoutValues_.numRowTiles;
            if ((newTile.index - tile.index) % rowTiles == 0)
              break;
          }

          this.focusElementIndex_ = newFocusIdx;
          break;

        default:
          return;
      }

      this.updateFocusElement_();

      e.preventDefault();
      e.stopPropagation();
    },

    /**
     * Ensure 0 <= this.focusElementIndex_ < this.focusableElements_.length,
     * make the focusable element at this.focusElementIndex_ (if any) eligible
     * for tab focus, and the previously-focused element not eligible.
     * @protected
     */
    updateFocusableElement: function() {
      if (this.focusableElements_.length == 0 || !this.selected) {
        this.focusElementIndex_ = -1;
        return;
      }

      this.focusElementIndex_ = Math.min(this.focusableElements_.length - 1,
                                         this.focusElementIndex_);
      this.focusElementIndex_ = Math.max(0, this.focusElementIndex_);

      var newFocusElement = this.focusableElements_[this.focusElementIndex_];
      var lastFocusElement = this.currentFocusElement_;
      if (lastFocusElement && lastFocusElement != newFocusElement)
        lastFocusElement.tabIndex = -1;

      newFocusElement.tabIndex = 1;
    },

    /**
     * Focuses the element at |this.focusElementIndex_|. Makes the previous
     * focus element, if any, no longer eligible for tab focus.
     * @private
     */
    updateFocusElement_: function() {
      this.updateFocusableElement();
      if (this.focusElementIndex_ >= 0)
        this.focusableElements_[this.focusElementIndex_].focus();
    },

    /**
     * The current focus element is that element which is eligible for focus.
     * @type {HTMLElement} The node.
     * @private
     */
    get currentFocusElement_() {
      return this.querySelector('.focusable[tabindex="1"]');
    },

    /**
     * Makes some calculations for tile layout. These change depending on
     * height, width, and the number of tiles.
     * TODO(estade): optimize calls to this function. Do nothing if the page is
     * hidden, but call before being shown.
     * @private
     */
    calculateLayoutValues_: function() {
      var grid = this.gridValues_;
      var availableSpace = this.tileGrid_.clientWidth - 2 * MIN_WIDE_MARGIN;
      var wide = availableSpace >= grid.minWideWidth;
      var numRowTiles = wide ? grid.maxColCount : grid.minColCount;

      var effectiveGridWidth = wide ?
          Math.min(Math.max(availableSpace, grid.minWideWidth),
                   grid.maxWideWidth) :
          grid.narrowWidth;
      var realTileValues = tileValuesForGrid(effectiveGridWidth, numRowTiles,
                                             grid.tileSpacingFraction);

      // leftMargin centers the grid within the avaiable space.
      var minMargin = wide ? MIN_WIDE_MARGIN : 0;
      var leftMargin =
          Math.max(minMargin,
                   (this.tileGrid_.clientWidth - effectiveGridWidth) / 2);

      var rowHeight = this.heightForWidth(realTileValues.tileWidth) +
          realTileValues.interTileSpacing;

      this.layoutValues_ = {
        colWidth: realTileValues.offsetX,
        gridWidth: effectiveGridWidth,
        leftMargin: leftMargin,
        numRowTiles: numRowTiles,
        rowHeight: rowHeight,
        tileWidth: realTileValues.tileWidth,
        wide: wide,
      };

      // We need to update the top margin as well.
      this.updateTopMargin_();

      this.firePageLayoutEvent_();
    },

    /**
     * Dispatches the custom pagelayout event.
     * @private
     */
    firePageLayoutEvent_: function() {
      cr.dispatchSimpleEvent(this, 'pagelayout', true, true);
    },

    /**
     * @return {number} The amount of margin that should be animated (in pixels)
     *     for the current grid layout.
     */
    getAnimatedLeftMargin_: function() {
      if (this.layoutValues_.wide)
        return 0;

      var grid = this.gridValues_;
      return (grid.minWideWidth - MIN_WIDE_MARGIN - grid.narrowWidth) / 2;
    },

    /**
     * Calculates the x/y coordinates for an element and moves it there.
     * @param {number} index The index of the element to be positioned.
     * @param {number=} opt_indexOffset If provided, this is added to |index|
     *     when positioning the tile. The effect is that the tile will be
     *     positioned in a non-default location.
     * @private
     */
    positionTile_: function(index, opt_indexOffset) {
      var grid = this.gridValues_;
      var layout = this.layoutValues_;

      var indexOffset = opt_indexOffset || 0;
      // Add the offset _after_ the modulus division. We might want to show the
      // tile off the side of the grid.
      var col = index % layout.numRowTiles + indexOffset;
      var row = Math.floor(index / layout.numRowTiles);
      // Calculate the final on-screen position for the tile.
      var realX = col * layout.colWidth + layout.leftMargin;
      var realY = row * layout.rowHeight;

      // Calculate the portion of the tile's position that should be animated.
      var animatedTileValues = layout.wide ?
          grid.wideTileValues : grid.narrowTileValues;
      // Animate the difference between three-wide and six-wide.
      var animatedLeftMargin = this.getAnimatedLeftMargin_();
      var animatedX = col * animatedTileValues.offsetX + animatedLeftMargin;
      var animatedY = row * (this.heightForWidth(animatedTileValues.tileWidth) +
                             animatedTileValues.interTileSpacing);

      var tile = this.tileElements_[index];
      tile.setGridPosition(animatedX, animatedY);
      tile.firstChild.setBounds(layout.tileWidth,
                                realX - animatedX,
                                realY - animatedY);

      // This code calculates whether the tile needs to show a clone of itself
      // wrapped around the other side of the tile grid.
      var offTheRight = col == layout.numRowTiles ||
          (col == layout.numRowTiles - 1 && tile.hasDoppleganger());
      var offTheLeft = col == -1 || (col == 0 && tile.hasDoppleganger());
      if (this.isCurrentDragTarget && (offTheRight || offTheLeft)) {
        var sign = offTheRight ? 1 : -1;
        tile.showDoppleganger(-layout.numRowTiles * layout.colWidth * sign,
                              layout.rowHeight * sign);
      } else {
        tile.clearDoppleganger();
      }

      if (index == this.tileElements_.length - 1) {
        this.tileGrid_.style.height = (realY + layout.rowHeight) + 'px';
        this.queueUpdateScrollbars_();
      }
    },

    /**
     * Gets the index of the tile that should occupy coordinate (x, y). Note
     * that this function doesn't care where the tiles actually are, and will
     * return an index even for the space between two tiles. This function is
     * effectively the inverse of |positionTile_|.
     * @param {number} x The x coordinate, in pixels, relative to the left of
     *     |this|.
     * @param {number} y The y coordinate, in pixels, relative to the top of
     *     |this|.
     * @return {number}
     * @private
     */
    getWouldBeIndexForPoint_: function(x, y) {
      var grid = this.gridValues_;
      var layout = this.layoutValues_;

      var gridClientRect = this.tileGrid_.getBoundingClientRect();
      var col = Math.floor((x - gridClientRect.left - layout.leftMargin) /
                           layout.colWidth);
      if (col < 0 || col >= layout.numRowTiles)
        return -1;

      if (isRTL())
        col = layout.numRowTiles - 1 - col;

      var row = Math.floor((y - gridClientRect.top) / layout.rowHeight);
      return row * layout.numRowTiles + col;
    },

    /**
     * Window resize event handler. Window resizes may trigger re-layouts.
     * @param {Object} e The resize event.
     */
    onResize_: function(e) {
      if (this.lastWidth_ == this.clientWidth &&
          this.lastHeight_ == this.clientHeight) {
        return;
      }

      this.calculateLayoutValues_();

      this.lastWidth_ = this.clientWidth;
      this.lastHeight_ = this.clientHeight;
      this.classList.add('animating-tile-page');
      this.heightChanged_();

      this.repositionTiles_();
    },

    /**
     * The tile grid has an image mask which fades at the edges. We only show
     * the mask when there is an active drag; it obscures doppleganger tiles
     * as they enter or exit the grid.
     * @private
     */
    updateMask_: function() {
      if (!this.isCurrentDragTarget) {
        this.tileGrid_.style.WebkitMaskBoxImage = '';
        return;
      }

      var leftMargin = this.layoutValues_.leftMargin;
      // The fade distance is the space between tiles.
      var fadeDistance = (this.gridValues_.tileSpacingFraction *
          this.layoutValues_.tileWidth);
      fadeDistance = Math.min(leftMargin, fadeDistance);
      // On Skia we don't use any fade because it works very poorly. See
      // http://crbug.com/99373
      if (!cr.isMac)
        fadeDistance = 1;
      var gradient =
          '-webkit-linear-gradient(left,' +
              'transparent, ' +
              'transparent ' + (leftMargin - fadeDistance) + 'px, ' +
              'black ' + leftMargin + 'px, ' +
              'black ' + (this.tileGrid_.clientWidth - leftMargin) + 'px, ' +
              'transparent ' + (this.tileGrid_.clientWidth - leftMargin +
                                fadeDistance) + 'px, ' +
              'transparent)';
      this.tileGrid_.style.WebkitMaskBoxImage = gradient;
    },

    updateTopMargin_: function() {
      var layout = this.layoutValues_;

      // The top margin is set so that the vertical midpoint of the grid will
      // be 1/3 down the page.
      var numTiles = this.tileCount +
          (this.isCurrentDragTarget && !this.withinPageDrag_ ? 1 : 0);
      var numRows = Math.max(1, Math.ceil(numTiles / layout.numRowTiles));
      var usedHeight = layout.rowHeight * numRows;
      var newMargin = document.documentElement.clientHeight / 3 -
          usedHeight / 3 - this.contentPadding;
      // The 'height' style attribute of topMargin is non-zero to work around
      // webkit's collapsing margin behavior, so we have to factor that into
      // our calculations here.
      newMargin = Math.max(newMargin, 0) - this.topMargin_.offsetHeight;

      // |newMargin| is the final margin we actually want to show. However,
      // part of that should be animated and part should not (for the same
      // reason as with leftMargin). The approach is to consider differences
      // when the layout changes from wide to narrow or vice versa as
      // 'animatable'. These differences accumulate in animatedTopMarginPx_,
      // while topMarginPx_ caches the real (total) margin. Either of these
      // calculations may come out to be negative, so we use margins as the
      // css property.

      if (typeof this.topMarginIsForWide_ == 'undefined')
        this.topMarginIsForWide_ = layout.wide;
      if (this.topMarginIsForWide_ != layout.wide) {
        this.animatedTopMarginPx_ += newMargin - this.topMarginPx_;
        this.topMargin_.style.marginBottom = toCssPx(this.animatedTopMarginPx_);
      }

      this.topMarginIsForWide_ = layout.wide;
      this.topMarginPx_ = newMargin;
      this.topMargin_.style.marginTop =
          toCssPx(this.topMarginPx_ - this.animatedTopMarginPx_);
    },

    /**
     * Handles final setup that can only happen after |this| is inserted into
     * the page.
     * @private
     */
    onNodeInsertedIntoDocument_: function(e) {
      this.calculateLayoutValues_();
      this.heightChanged_();
    },

    /**
     * Called when the height of |this| has changed: update the size of
     * tileGrid.
     * @private
     */
    heightChanged_: function() {
      // The tile grid will expand to the bottom footer, or enough to hold all
      // the tiles, whichever is greater. It would be nicer if tilePage were
      // a flex box, and the tile grid could be box-flex: 1, but this exposes a
      // bug where repositioning tiles will cause the scroll position to reset.
      this.tileGrid_.style.minHeight = this.clientHeight -
          this.tileGrid_.offsetTop - this.content_.offsetTop + 'px';
    },

    /**
     * Scrolls the page in response to an mousewheel event, although the event
     * may have been triggered on a different element. Return true if the
     * event triggered scrolling, and false otherwise.
     * This is called explicitly, which allows a consistent experience whether
     * the user scrolls on the page or on the page switcher, because this
     * function provides a common conversion factor between wheel delta and
     * scroll delta.
     * @param {Event} e The mousewheel event.
     */
    handleMouseWheel: function(e) {
      // The ctrl-wheel should triggle the zoom in/out actions in Chromium for
      // all pages.
      if (e.wheelDeltaY == 0 || e.ctrlKey)
        return false;

      this.content_.scrollTop -= e.wheelDeltaY / 3;
      return true;
    },

    /**
     * Handler for the 'scroll' event on |content_|.
     * @param {Event} e The scroll event.
     * @private
     */
    onScroll_: function(e) {
      this.queueUpdateScrollbars_();
    },

    /**
     * ID of scrollbar update timer. If 0, there's no scrollbar re-calc queued.
     * @private
     */
    scrollbarUpdate_: 0,

    /**
     * Queues an update on the custom scrollbar. Used for two reasons: first,
     * coalescing of multiple updates, and second, because action like
     * repositioning a tile can require a delay before they affect values
     * like clientHeight.
     * @private
     */
    queueUpdateScrollbars_: function() {
      if (this.scrollbarUpdate_)
        return;

      this.scrollbarUpdate_ = window.setTimeout(
          this.doUpdateScrollbars_.bind(this), 0);
    },

    /**
     * Does the work of calculating the visibility, height and position of the
     * scrollbar thumb (there is no track or buttons).
     * @private
     */
    doUpdateScrollbars_: function() {
      this.scrollbarUpdate_ = 0;

      var content = this.content_;

      // Adjust scroll-height to account for possible header-bar.
      var adjustedScrollHeight = content.scrollHeight - content.offsetTop;

      if (adjustedScrollHeight <= content.clientHeight) {
        this.scrollbar_.hidden = true;
        return;
      } else {
        this.scrollbar_.hidden = false;
      }

      var thumbTop = content.offsetTop +
          content.scrollTop / adjustedScrollHeight * content.clientHeight;
      var thumbHeight = content.clientHeight / adjustedScrollHeight *
          this.clientHeight;

      this.scrollbar_.style.top = thumbTop + 'px';
      this.scrollbar_.style.height = thumbHeight + 'px';
      this.firePageLayoutEvent_();
    },

    /**
     * Get the height for a tile of a certain width. Override this function to
     * get non-square tiles.
     * @param {number} width The pixel width of a tile.
     * @return {number} The height for |width|.
     */
    heightForWidth: function(width) {
      return width;
    },

    /** Dragging **/

    get isCurrentDragTarget() {
      return this.dragWrapper_.isCurrentDragTarget;
    },

    /**
     * Thunk for dragleave events fired on |tileGrid_|.
     * @param {Event} e A MouseEvent for the drag.
     */
    doDragLeave: function(e) {
      this.cleanupDrag();
    },

    /**
     * Performs all actions necessary when a drag enters the tile page.
     * @param {Event} e A mouseover event for the drag enter.
     */
    doDragEnter: function(e) {
      // Applies the mask so doppleganger tiles disappear into the fog.
      this.updateMask_();

      this.classList.add('animating-tile-page');
      this.withinPageDrag_ = this.contains(currentlyDraggingTile);
      this.dragItemIndex_ = this.withinPageDrag_ ?
          currentlyDraggingTile.index : this.tileElements_.length;
      this.currentDropIndex_ = this.dragItemIndex_;

      // The new tile may change the number of rows, hence the top margin
      // will change.
      if (!this.withinPageDrag_)
        this.updateTopMargin_();

      this.doDragOver(e);
    },

    /**
     * Performs all actions necessary when the user moves the cursor during
     * a drag over the tile page.
     * @param {Event} e A mouseover event for the drag over.
     */
    doDragOver: function(e) {
      e.preventDefault();

      this.setDropEffect(e.dataTransfer);
      var newDragIndex = this.getWouldBeIndexForPoint_(e.pageX, e.pageY);
      if (newDragIndex < 0 || newDragIndex >= this.tileElements_.length)
        newDragIndex = this.dragItemIndex_;
      this.updateDropIndicator_(newDragIndex);
    },

    /**
     * Performs all actions necessary when the user completes a drop.
     * @param {Event} e A mouseover event for the drag drop.
     */
    doDrop: function(e) {
      e.stopPropagation();
      e.preventDefault();

      var index = this.currentDropIndex_;
      // Only change data if this was not a 'null drag'.
      if (!((index == this.dragItemIndex_) && this.withinPageDrag_)) {
        var adjustedIndex = this.currentDropIndex_ +
            (index > this.dragItemIndex_ ? 1 : 0);
        if (this.withinPageDrag_) {
          this.tileGrid_.insertBefore(
              currentlyDraggingTile,
              this.tileElements_[adjustedIndex]);
          this.tileMoved(currentlyDraggingTile, this.dragItemIndex_);
        } else {
          var originalPage = currentlyDraggingTile ?
              currentlyDraggingTile.tilePage : null;
          this.addDragData(e.dataTransfer, adjustedIndex);
          if (originalPage)
            originalPage.cleanupDrag();
        }

        // Dropping the icon may cause topMargin to change, but changing it
        // now would cause everything to move (annoying), so we leave it
        // alone. The top margin will be re-calculated next time the window is
        // resized or the page is selected.
      }

      this.classList.remove('animating-tile-page');
      this.cleanupDrag();
    },

    /**
     * Appends the currently dragged tile to the end of the page. Called
     * from outside the page, e.g. when dropping on a nav dot.
     */
    appendDraggingTile: function() {
      var originalPage = currentlyDraggingTile.tilePage;
      if (originalPage == this)
        return;

      this.addDragData(null, this.tileElements_.length);
      if (originalPage)
        originalPage.cleanupDrag();
    },

    /**
     * Makes sure all the tiles are in the right place after a drag is over.
     */
    cleanupDrag: function() {
      this.repositionTiles_(currentlyDraggingTile);
      // Remove the drag mask.
      this.updateMask_();
    },

    /**
     * Reposition all the tiles (possibly ignoring one).
     * @param {Node=} opt_ignoreNode An optional node to ignore.
     * @private
     */
    repositionTiles_: function(opt_ignoreNode) {
      for (var i = 0; i < this.tileElements_.length; i++) {
        if (!opt_ignoreNode || opt_ignoreNode !== this.tileElements_[i])
          this.positionTile_(i);
      }
    },

    /**
     * Updates the visual indicator for the drop location for the active drag.
     * @param {number} newDragIndex
     * @private
     */
    updateDropIndicator_: function(newDragIndex) {
      var oldDragIndex = this.currentDropIndex_;
      if (newDragIndex == oldDragIndex)
        return;

      var repositionStart = Math.min(newDragIndex, oldDragIndex);
      var repositionEnd = Math.max(newDragIndex, oldDragIndex);

      for (var i = repositionStart; i <= repositionEnd; i++) {
        if (i == this.dragItemIndex_)
          continue;
        else if (i > this.dragItemIndex_)
          var adjustment = i <= newDragIndex ? -1 : 0;
        else
          var adjustment = i >= newDragIndex ? 1 : 0;

        this.positionTile_(i, adjustment);
      }
      this.currentDropIndex_ = newDragIndex;
    },

    /**
     * Checks if a page can accept a drag with the given data.
     * @param {Event} e The drag event if the drag object. Implementations will
     *     likely want to check |e.dataTransfer|.
     * @return {boolean} True if this page can handle the drag.
     */
    shouldAcceptDrag: function(e) {
      return false;
    },

    /**
     * Called to accept a drag drop. Will not be called for in-page drops.
     * @param {Object} dataTransfer The data transfer object that holds the drop
     *     data. This should only be used if currentlyDraggingTile is null.
     * @param {number} index The tile index at which the drop occurred.
     */
    addDragData: function(dataTransfer, index) {
      assertNotReached();
    },

    /**
     * Called when a tile has been moved (via dragging). Override this to make
     * backend updates.
     * @param {Node} draggedTile The tile that was dropped.
     * @param {number} prevIndex The previous index of the tile.
     */
    tileMoved: function(draggedTile, prevIndex) {
    },

    /**
     * Sets the drop effect on |dataTransfer| to the desired value (e.g.
     * 'copy').
     * @param {Object} dataTransfer The drag event dataTransfer object.
     */
    setDropEffect: function(dataTransfer) {
      assertNotReached();
    },
  };

  return {
    getCurrentlyDraggingTile: getCurrentlyDraggingTile,
    setCurrentDropEffect: setCurrentDropEffect,
    // Not used outside, just for usage in JSDoc inside this file.
    Tile: Tile,
    TilePage: TilePage,
  };
});
