// Copyright 2016 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.

/**
 * @fileoverview Behavior for handling display layout, specifically
 *     edge snapping and collisions.
 */

/** @polymerBehavior */
const LayoutBehavior = {
  properties: {
    /**
     * Array of display layouts.
     * @type {!Array<!chrome.system.display.DisplayLayout>}
     */
    layouts: Array,

    /**
     * Whether or not mirroring is enabled.
     * @type {boolean}
     */
    mirroring: false,
  },

  /** @private {!Map<string, chrome.system.display.Bounds>} */
  displayBoundsMap_: new Map(),

  /** @private {!Map<string, chrome.system.display.DisplayLayout>} */
  displayLayoutMap_: new Map(),

  /**
   * The calculated bounds used for generating the div bounds.
   * @private {!Map<string, chrome.system.display.Bounds>}
   */
  calculatedBoundsMap_: new Map(),

  /** @private {string} */
  dragLayoutId_: '',

  /** @private {string} */
  dragParentId_: '',

  /** @private {!chrome.system.display.Bounds|undefined} */
  dragBounds_: undefined,

  /** @private {!chrome.system.display.LayoutPosition|undefined} */
  dragLayoutPosition_: undefined,

  /**
   * @param {!Array<!chrome.system.display.DisplayUnitInfo>} displays
   * @param {!Array<!chrome.system.display.DisplayLayout>} layouts
   */
  initializeDisplayLayout: function(displays, layouts) {
    this.dragLayoutId_ = '';
    this.dragParentId_ = '';

    this.mirroring = displays.length > 0 && !!displays[0].mirroringSourceId;

    this.displayBoundsMap_.clear();
    for (const display of displays) {
      this.displayBoundsMap_.set(display.id, display.bounds);
    }
    this.displayLayoutMap_.clear();
    for (const layout of layouts) {
      this.displayLayoutMap_.set(layout.id, layout);
    }
    this.calculatedBoundsMap_.clear();
    for (const display of displays) {
      if (!this.calculatedBoundsMap_.has(display.id)) {
        const bounds = display.bounds;
        this.calculateBounds_(display.id, bounds.width, bounds.height);
      }
    }
  },

  /**
   * Called when a drag event occurs. Checks collisions and updates the layout.
   * @param {string} id
   * @param {!chrome.system.display.Bounds} newBounds The new calculated
   *     bounds for the display.
   * @return {!chrome.system.display.Bounds}
   */
  updateDisplayBounds: function(id, newBounds) {
    this.dragLayoutId_ = id;

    // Find the closest parent.
    const closestId = this.findClosest_(id, newBounds);
    assert(closestId);

    // Find the closest edge.
    const closestBounds = this.getCalculatedDisplayBounds(closestId);
    const layoutPosition =
        this.getLayoutPositionForBounds_(newBounds, closestBounds);

    // Snap to the closest edge.
    const snapPos = this.snapBounds_(newBounds, closestId, layoutPosition);
    newBounds.left = snapPos.x;
    newBounds.top = snapPos.y;

    // Calculate the new bounds and delta.
    const oldBounds = this.dragBounds_ || this.getCalculatedDisplayBounds(id);
    const deltaPos = {
      x: newBounds.left - oldBounds.left,
      y: newBounds.top - oldBounds.top
    };

    // Check for collisions after snapping. This should not collide with the
    // closest parent.
    this.collideAndModifyDelta_(id, oldBounds, deltaPos);

    // If the edge changed, update and highlight it.
    if (layoutPosition != this.dragLayoutPosition_ ||
        closestId != this.dragParentId_) {
      this.dragLayoutPosition_ = layoutPosition;
      this.dragParentId_ = closestId;
      this.highlightEdge_(closestId, layoutPosition);
    }

    newBounds.left = oldBounds.left + deltaPos.x;
    newBounds.top = oldBounds.top + deltaPos.y;

    this.dragBounds_ = newBounds;

    return newBounds;
  },

  /**
   * Called when dragging ends. Sends the updated layout to chrome.
   * @param {string} id
   */
  finishUpdateDisplayBounds: function(id) {
    this.highlightEdge_('', undefined);  // Remove any highlights.
    if (id != this.dragLayoutId_ || !this.dragBounds_ ||
        !this.dragLayoutPosition_) {
      return;
    }

    const layout = this.displayLayoutMap_.get(id);

    let orphanIds;
    if (!layout || layout.parentId == '') {
      // Primary display. Set the calculated position to |dragBounds_|.
      this.setCalculatedDisplayBounds_(id, this.dragBounds_);

      // We cannot re-parent the primary display, so instead make all other
      // displays orphans and clear their calculated bounds.
      orphanIds = this.findChildren_(id, true /* recurse */);

      // Re-parent |dragParentId_|. It will be forced to parent to the dragged
      // display since it is the only non-orphan.
      this.reparentOrphan_(this.dragParentId_, orphanIds);
      orphanIds.splice(orphanIds.indexOf(this.dragParentId_), 1);
    } else {
      // All immediate children of |layout| will need to be re-parented.
      orphanIds = this.findChildren_(id, false /* do not recurse */);

      // When re-parenting to a descendant, also parent any immediate child to
      // drag display's current parent.
      let topLayout = this.displayLayoutMap_.get(this.dragParentId_);
      while (topLayout && topLayout.parentId != '') {
        if (topLayout.parentId == id) {
          topLayout.parentId = layout.parentId;
          break;
        }
        topLayout = this.displayLayoutMap_.get(topLayout.parentId);
      }

      // Re-parent the dragged display.
      layout.parentId = this.dragParentId_;
      this.updateOffsetAndPosition_(
          this.dragBounds_, this.dragLayoutPosition_, layout);
    }

    // Update any orphaned children. This may cause the dragged display to
    // be re-attached if it was attached to a child.
    this.updateOrphans_(orphanIds);

    // Send the updated layouts.
    chrome.system.display.setDisplayLayout(this.layouts, function() {
      if (chrome.runtime.lastError) {
        console.error(
            'setDisplayLayout Error: ' + chrome.runtime.lastError.message);
      }
    });
  },

  /**
   * @param {string} displayId
   * @param {boolean=} opt_notest Set to true if bounds may not be set.
   * @return {!chrome.system.display.Bounds} bounds
   */
  getCalculatedDisplayBounds: function(displayId, opt_notest) {
    const bounds = this.calculatedBoundsMap_.get(displayId);
    assert(opt_notest || bounds);
    return bounds;
  },

  /**
   * @param {string} displayId
   * @param {!chrome.system.display.Bounds|undefined} bounds
   * @private
   */
  setCalculatedDisplayBounds_: function(displayId, bounds) {
    assert(bounds);
    this.calculatedBoundsMap_.set(
        displayId,
        /** @type {!chrome.system.display.Bounds} */
        (Object.assign({}, bounds)));
  },

  /**
   * Re-parents all entries in |orphanIds| and any children.
   * @param {!Array<string>} orphanIds The list of ids affected by the move.
   * @private
   */
  updateOrphans_: function(orphanIds) {
    const orphans = orphanIds.slice();
    for (let i = 0; i < orphanIds.length; ++i) {
      const orphan = orphanIds[i];
      const newOrphans = this.findChildren_(orphan, true /* recurse */);
      // If the dragged display was re-parented to one of its children,
      // there may be duplicates so merge the lists.
      for (let ii = 0; ii < newOrphans.length; ++ii) {
        const o = newOrphans[ii];
        if (!orphans.includes(o))
          orphans.push(o);
      }
    }

    // Remove each orphan from the list as it is re-parented so that
    // subsequent orphans can be parented to it.
    while (orphans.length) {
      const orphanId = orphans.shift();
      this.reparentOrphan_(orphanId, orphans);
    }
  },

  /**
   * Re-parents the orphan to a layout that is not a member of
   * |otherOrphanIds|.
   * @param {string} orphanId The id of the orphan to re-parent.
   * @param {Array<string>} otherOrphanIds The list of ids of other orphans
   *     to ignore when re-parenting.
   * @private
   */
  reparentOrphan_: function(orphanId, otherOrphanIds) {
    const layout = this.displayLayoutMap_.get(orphanId);
    assert(layout);
    if (orphanId == this.dragId_ && layout.parentId != '') {
      this.setCalculatedDisplayBounds_(orphanId, this.dragBounds_);
      return;
    }
    const bounds = this.getCalculatedDisplayBounds(orphanId);

    // Find the closest parent.
    const newParentId = this.findClosest_(orphanId, bounds, otherOrphanIds);
    assert(newParentId != '');
    layout.parentId = newParentId;

    // Find the closest edge.
    const parentBounds = this.getCalculatedDisplayBounds(newParentId);
    const layoutPosition =
        this.getLayoutPositionForBounds_(bounds, parentBounds);

    // Move from the nearest corner to the desired location and get the delta.
    const cornerBounds = this.getCornerBounds_(bounds, parentBounds);
    const desiredPos = this.snapBounds_(bounds, newParentId, layoutPosition);
    const deltaPos = {
      x: desiredPos.x - cornerBounds.left,
      y: desiredPos.y - cornerBounds.top
    };

    // Check for collisions.
    this.collideAndModifyDelta_(orphanId, cornerBounds, deltaPos);
    const desiredBounds = {
      left: cornerBounds.left + deltaPos.x,
      top: cornerBounds.top + deltaPos.y,
      width: bounds.width,
      height: bounds.height
    };

    this.updateOffsetAndPosition_(desiredBounds, layoutPosition, layout);
  },

  /**
   * @param {string} parentId
   * @param {boolean} recurse Include descendants of children.
   * @return {!Array<string>}
   * @private
   */
  findChildren_: function(parentId, recurse) {
    let children = [];
    this.displayLayoutMap_.forEach((value, key) => {
      const childId = key;
      if (childId != parentId && value.parentId == parentId) {
        // Insert immediate children at the front of the array.
        children.unshift(childId);
        if (recurse) {
          // Descendants get added to the end of the list.
          children = children.concat(this.findChildren_(childId, true));
        }
      }
    });
    return children;
  },

  /**
   * Recursively calculates the absolute bounds of a display.
   * Caches the display bounds so that parent bounds are only calculated once.
   * @param {string} id
   * @param {number} width
   * @param {number} height
   * @private
   */
  calculateBounds_: function(id, width, height) {
    let left, top;
    const layout = this.displayLayoutMap_.get(id);
    if (this.mirroring || !layout || !layout.parentId) {
      left = -width / 2;
      top = -height / 2;
    } else {
      if (!this.calculatedBoundsMap_.has(layout.parentId)) {
        const pbounds = this.displayBoundsMap_.get(layout.parentId);
        this.calculateBounds_(layout.parentId, pbounds.width, pbounds.height);
      }
      const parentBounds = this.getCalculatedDisplayBounds(layout.parentId);
      left = parentBounds.left;
      top = parentBounds.top;
      switch (layout.position) {
        case chrome.system.display.LayoutPosition.TOP:
          left += layout.offset;
          top -= height;
          break;
        case chrome.system.display.LayoutPosition.RIGHT:
          left += parentBounds.width;
          top += layout.offset;
          break;
        case chrome.system.display.LayoutPosition.BOTTOM:
          left += layout.offset;
          top += parentBounds.height;
          break;
        case chrome.system.display.LayoutPosition.LEFT:
          left -= width;
          top += layout.offset;
          break;
      }
    }
    const result = {
      left: left,
      top: top,
      width: width,
      height: height,
    };
    this.setCalculatedDisplayBounds_(id, result);
  },

  /**
   * Finds the display closest to |bounds| ignoring |opt_ignoreIds|.
   * @param {string} displayId
   * @param {!chrome.system.display.Bounds} bounds
   * @param {Array<string>=} opt_ignoreIds Ids to ignore.
   * @return {string}
   * @private
   */
  findClosest_: function(displayId, bounds, opt_ignoreIds) {
    const x = bounds.left + bounds.width / 2;
    const y = bounds.top + bounds.height / 2;
    let closestId = '';
    let closestDelta2 = 0;
    const keys = this.calculatedBoundsMap_.keys();
    for (let iter = keys.next(); !iter.done; iter = keys.next()) {
      const otherId = iter.value;
      if (otherId == displayId)
        continue;
      if (opt_ignoreIds && opt_ignoreIds.includes(otherId))
        continue;
      const otherBounds = this.getCalculatedDisplayBounds(otherId);
      const left = otherBounds.left;
      const top = otherBounds.top;
      const width = otherBounds.width;
      const height = otherBounds.height;
      if (x >= left && x < left + width && y >= top && y < top + height)
        return otherId;  // point is inside rect
      let dx, dy;
      if (x < left)
        dx = left - x;
      else if (x > left + width)
        dx = x - (left + width);
      else
        dx = 0;
      if (y < top)
        dy = top - y;
      else if (y > top + height)
        dy = y - (top + height);
      else
        dy = 0;
      const delta2 = dx * dx + dy * dy;
      if (closestId == '' || delta2 < closestDelta2) {
        closestId = otherId;
        closestDelta2 = delta2;
      }
    }
    return closestId;
  },

  /**
   * Calculates the LayoutPosition for |bounds| relative to |parentId|.
   * @param {!chrome.system.display.Bounds} bounds
   * @param {!chrome.system.display.Bounds} parentBounds
   * @return {!chrome.system.display.LayoutPosition}
   */
  getLayoutPositionForBounds_: function(bounds, parentBounds) {
    // Translate bounds from top-left to center.
    const x = bounds.left + bounds.width / 2;
    const y = bounds.top + bounds.height / 2;

    // Determine the distance from the new bounds to both of the near edges.
    const left = parentBounds.left;
    const top = parentBounds.top;
    const width = parentBounds.width;
    const height = parentBounds.height;

    // Signed deltas to the center.
    const dx = x - (left + width / 2);
    const dy = y - (top + height / 2);

    // Unsigned distance to each edge.
    const distx = Math.abs(dx) - width / 2;
    const disty = Math.abs(dy) - height / 2;

    if (distx > disty) {
      if (dx < 0)
        return chrome.system.display.LayoutPosition.LEFT;
      else
        return chrome.system.display.LayoutPosition.RIGHT;
    } else {
      if (dy < 0)
        return chrome.system.display.LayoutPosition.TOP;
      else
        return chrome.system.display.LayoutPosition.BOTTOM;
    }
  },

  /**
   * Modifies |bounds| to the position closest to it along the edge of
   * |parentId| specified by |layoutPosition|.
   * @param {!chrome.system.display.Bounds} bounds
   * @param {string} parentId
   * @param {!chrome.system.display.LayoutPosition} layoutPosition
   * @return {!{x: number, y: number}}
   */
  snapBounds_: function(bounds, parentId, layoutPosition) {
    const parentBounds = this.getCalculatedDisplayBounds(parentId);

    let x;
    if (layoutPosition == chrome.system.display.LayoutPosition.LEFT) {
      x = parentBounds.left - bounds.width;
    } else if (layoutPosition == chrome.system.display.LayoutPosition.RIGHT) {
      x = parentBounds.left + parentBounds.width;
    } else {
      x = this.snapToX_(bounds, parentBounds);
    }

    let y;
    if (layoutPosition == chrome.system.display.LayoutPosition.TOP) {
      y = parentBounds.top - bounds.height;
    } else if (layoutPosition == chrome.system.display.LayoutPosition.BOTTOM) {
      y = parentBounds.top + parentBounds.height;
    } else {
      y = this.snapToY_(bounds, parentBounds);
    }

    return {x: x, y: y};
  },

  /**
   * Snaps a horizontal value, see snapToEdge.
   * @param {!chrome.system.display.Bounds} newBounds
   * @param {!chrome.system.display.Bounds} parentBounds
   * @param {number=} opt_snapDistance Provide to override the snap distance.
   *     0 means snap from any distance.
   * @return {number}
   */
  snapToX_: function(newBounds, parentBounds, opt_snapDistance) {
    return this.snapToEdge_(
        newBounds.left, newBounds.width, parentBounds.left, parentBounds.width,
        opt_snapDistance);
  },

  /**
   * Snaps a vertical value, see snapToEdge.
   * @param {!chrome.system.display.Bounds} newBounds
   * @param {!chrome.system.display.Bounds} parentBounds
   * @param {number=} opt_snapDistance Provide to override the snap distance.
   *     0 means snap from any distance.
   * @return {number}
   */
  snapToY_: function(newBounds, parentBounds, opt_snapDistance) {
    return this.snapToEdge_(
        newBounds.top, newBounds.height, parentBounds.top, parentBounds.height,
        opt_snapDistance);
  },

  /**
   * Snaps the region [point, width] to [basePoint, baseWidth] if
   * the [point, width] is close enough to the base's edge.
   * @param {number} point The starting point of the region.
   * @param {number} width The width of the region.
   * @param {number} basePoint The starting point of the base region.
   * @param {number} baseWidth The width of the base region.
   * @param {number=} opt_snapDistance Provide to override the snap distance.
   *     0 means snap at any distance.
   * @return {number} The moved point. Returns the point itself if it doesn't
   *     need to snap to the edge.
   * @private
   */
  snapToEdge_: function(point, width, basePoint, baseWidth, opt_snapDistance) {
    // If the edge of the region is smaller than this, it will snap to the
    // base's edge.
    const SNAP_DISTANCE_PX = 16;
    const snapDist =
        (opt_snapDistance !== undefined) ? opt_snapDistance : SNAP_DISTANCE_PX;

    const startDiff = Math.abs(point - basePoint);
    const endDiff = Math.abs(point + width - (basePoint + baseWidth));
    // Prefer the closer one if both edges are close enough.
    if ((!snapDist || startDiff < snapDist) && startDiff < endDiff)
      return basePoint;
    else if (!snapDist || endDiff < snapDist)
      return basePoint + baseWidth - width;

    return point;
  },

  /**
   * Intersects |layout| with each other layout and reduces |deltaPos| to
   * avoid any collisions (or sets it to [0,0] if the display can not be moved
   * in the direction of |deltaPos|).
   * Note: this assumes that deltaPos is already 'snapped' to the parent edge,
   * and therefore will not collide with the parent, i.e. this is to prevent
   * overlapping with displays other than the parent.
   * @param {string} id
   * @param {!chrome.system.display.Bounds} bounds
   * @param {!{x: number, y: number}} deltaPos
   */
  collideAndModifyDelta_: function(id, bounds, deltaPos) {
    const keys = this.calculatedBoundsMap_.keys();
    const others = new Set(keys);
    others.delete(id);
    let checkCollisions = true;
    while (checkCollisions) {
      checkCollisions = false;
      const othersValues = others.values();
      for (let iter = othersValues.next(); !iter.done;
           iter = othersValues.next()) {
        const otherId = iter.value;
        const otherBounds = this.getCalculatedDisplayBounds(otherId);
        if (this.collideWithBoundsAndModifyDelta_(
                bounds, otherBounds, deltaPos)) {
          if (deltaPos.x == 0 && deltaPos.y == 0)
            return;
          others.delete(otherId);
          checkCollisions = true;
          break;
        }
      }
    }
  },

  /**
   * Intersects |bounds| with |otherBounds|. If there is a collision, modifies
   * |deltaPos| to limit movement to a single axis and avoid the collision
   * and returns true. See note for |collideAndModifyDelta_|.
   * @param {!chrome.system.display.Bounds} bounds
   * @param {!chrome.system.display.Bounds} otherBounds
   * @param {!{x: number, y: number}} deltaPos
   * @return {boolean} Whether there was a collision.
   */
  collideWithBoundsAndModifyDelta_: function(bounds, otherBounds, deltaPos) {
    const newX = bounds.left + deltaPos.x;
    const newY = bounds.top + deltaPos.y;

    if ((newX + bounds.width <= otherBounds.left) ||
        (newX >= otherBounds.left + otherBounds.width) ||
        (newY + bounds.height <= otherBounds.top) ||
        (newY >= otherBounds.top + otherBounds.height)) {
      return false;
    }

    // |deltaPos| should already be restricted to X or Y. This shortens the
    // delta to stay outside the bounds, however it does not change the sign of
    // the delta, i.e. it does not "push" the point outside the bounds if
    // the point is already inside.
    if (Math.abs(deltaPos.x) > Math.abs(deltaPos.y)) {
      deltaPos.y = 0;
      let snapDeltaX;
      if (deltaPos.x > 0) {
        snapDeltaX =
            Math.max(0, (otherBounds.left - bounds.width) - bounds.left);
      } else {
        snapDeltaX =
            Math.min(0, (otherBounds.left + otherBounds.width) - bounds.left);
      }
      deltaPos.x = snapDeltaX;
    } else {
      deltaPos.x = 0;
      let snapDeltaY;
      if (deltaPos.y > 0) {
        snapDeltaY =
            Math.min(0, (otherBounds.top - bounds.height) - bounds.top);
      } else if (deltaPos.y < 0) {
        snapDeltaY =
            Math.max(0, (otherBounds.top + otherBounds.height) - bounds.top);
      } else {
        snapDeltaY = 0;
      }
      deltaPos.y = snapDeltaY;
    }

    return true;
  },

  /**
   * Updates the offset for |layout| from |bounds|.
   * @param {!chrome.system.display.Bounds} bounds
   * @param {!chrome.system.display.LayoutPosition} position
   * @param {!chrome.system.display.DisplayLayout} layout
   */
  updateOffsetAndPosition_: function(bounds, position, layout) {
    layout.position = position;
    if (!layout.parentId) {
      layout.offset = 0;
      return;
    }

    // Offset is calculated from top or left edge.
    const parentBounds = this.getCalculatedDisplayBounds(layout.parentId);
    let offset, minOffset, maxOffset;
    if (position == chrome.system.display.LayoutPosition.LEFT ||
        position == chrome.system.display.LayoutPosition.RIGHT) {
      offset = bounds.top - parentBounds.top;
      minOffset = -bounds.height;
      maxOffset = parentBounds.height;
    } else {
      offset = bounds.left - parentBounds.left;
      minOffset = -bounds.width;
      maxOffset = parentBounds.width;
    }
    const MIN_OFFSET_OVERLAP = 50;
    minOffset += MIN_OFFSET_OVERLAP;
    maxOffset -= MIN_OFFSET_OVERLAP;
    layout.offset = Math.max(minOffset, Math.min(offset, maxOffset));

    // Update the calculated bounds to match the new offset.
    this.calculateBounds_(layout.id, bounds.width, bounds.height);
  },

  /**
   * Returns |bounds| translated to touch the closest corner of |parentBounds|.
   * @param {!chrome.system.display.Bounds} bounds
   * @param {!chrome.system.display.Bounds} parentBounds
   * @return {!chrome.system.display.Bounds}
   * @private
   */
  getCornerBounds_: function(bounds, parentBounds) {
    let x;
    if (bounds.left > parentBounds.left + parentBounds.width / 2)
      x = parentBounds.left + parentBounds.width;
    else
      x = parentBounds.left - bounds.width;
    let y;
    if (bounds.top > parentBounds.top + parentBounds.height / 2)
      y = parentBounds.top + parentBounds.height;
    else
      y = parentBounds.top - bounds.height;
    return {
      left: x,
      top: y,
      width: bounds.width,
      height: bounds.height,
    };
  },

  /**
   * Highlights the edge of the div associated with |id| based on
   * |layoutPosition| and removes any other highlights. If |layoutPosition| is
   * undefined, removes all highlights.
   * @param {string} id
   * @param {chrome.system.display.LayoutPosition|undefined} layoutPosition
   * @private
   */
  highlightEdge_: function(id, layoutPosition) {
    for (let i = 0; i < this.layouts.length; ++i) {
      const layout = this.layouts[i];
      const highlight = (layout.id == id) ? layoutPosition : undefined;
      const div = this.$$('#_' + layout.id);
      div.classList.toggle(
          'highlight-right',
          highlight == chrome.system.display.LayoutPosition.RIGHT);
      div.classList.toggle(
          'highlight-left',
          highlight == chrome.system.display.LayoutPosition.LEFT);
      div.classList.toggle(
          'highlight-top',
          highlight == chrome.system.display.LayoutPosition.TOP);
      div.classList.toggle(
          'highlight-bottom',
          highlight == chrome.system.display.LayoutPosition.BOTTOM);
    }
  },
};
