/**
 * @license
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed 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.
 */
(function() {
  'use strict';

  Polymer({
    is: 'gr-diff-highlight',

    properties: {
      /** @type {!Array<!Gerrit.HoveredRange>} */
      commentRanges: {
        type: Array,
        notify: true,
      },
      loggedIn: Boolean,
      /**
       * querySelector can return null, so needs to be nullable.
       *
       * @type {?HTMLElement}
       * */
      _cachedDiffBuilder: Object,
    },

    listeners: {
      'comment-thread-mouseleave': '_handleCommentThreadMouseleave',
      'comment-thread-mouseenter': '_handleCommentThreadMouseenter',
      'create-range-comment': '_createRangeComment',
    },

    get diffBuilder() {
      if (!this._cachedDiffBuilder) {
        this._cachedDiffBuilder =
            Polymer.dom(this).querySelector('gr-diff-builder');
      }
      return this._cachedDiffBuilder;
    },


    isRangeSelected() {
      return !!this.$$('gr-selection-action-box');
    },

    /**
     * Determines side/line/range for a DOM selection and shows a tooltip.
     *
     * With native shadow DOM, gr-diff-highlight cannot access a selection that
     * references the DOM elements making up the diff because they are in the
     * shadow DOM the gr-diff element. For this reason, we listen to the
     * selectionchange event and retrieve the selection in gr-diff, and then
     * call this method to process the Selection.
     *
     * @param {Selection} selection A DOM Selection living in the shadow DOM of
     *     the diff element.
     * @param {boolean} isMouseUp If true, this is called due to a mouseup
     *     event, in which case we might want to immediately create a comment.
     */
    handleSelectionChange(selection, isMouseUp) {
      // Can't use up or down events to handle selection started and/or ended in
      // in comment threads or outside of diff.
      // Debounce removeActionBox to give it a chance to react to click/tap.
      this._removeActionBoxDebounced();
      this.debounce(
          'selectionChange', () => this._handleSelection(selection, isMouseUp),
          200);
    },

    _getThreadEl(e) {
      const path = Polymer.dom(e).path || [];
      for (const pathEl of path) {
        if (pathEl.classList.contains('comment-thread')) return pathEl;
      }
      return null;
    },

    _handleCommentThreadMouseenter(e) {
      const threadEl = this._getThreadEl(e);
      const index = this._indexForThreadEl(threadEl);

      if (index !== undefined) {
        this.set(['commentRanges', index, 'hovering'], true);
      }
    },

    _handleCommentThreadMouseleave(e) {
      const threadEl = this._getThreadEl(e);
      const index = this._indexForThreadEl(threadEl);

      if (index !== undefined) {
        this.set(['commentRanges', index, 'hovering'], false);
      }
    },

    _indexForThreadEl(threadEl) {
      const side = threadEl.getAttribute('comment-side');
      const range = JSON.parse(threadEl.getAttribute('range'));

      if (!range) return undefined;

      return this._indexOfCommentRange(side, range);
    },

    _indexOfCommentRange(side, range) {
      function rangesEqual(a, b) {
        if (!a && !b) {
          return true;
        }
        if (!a || !b) {
          return false;
        }
        return a.start_line === b.start_line &&
            a.start_character === b.start_character &&
            a.end_line === b.end_line &&
            a.end_character === b.end_character;
      }

      return this.commentRanges.findIndex(commentRange =>
          commentRange.side === side && rangesEqual(commentRange.range, range));
    },

    /**
     * Get current normalized selection.
     * Merges multiple ranges, accounts for triple click, accounts for
     * syntax highligh, convert native DOM Range objects to Gerrit concepts
     * (line, side, etc).
     * @param {Selection} selection
     * @return {({
     *   start: {
     *     node: Node,
     *     side: string,
     *     line: Number,
     *     column: Number
     *   },
     *   end: {
     *     node: Node,
     *     side: string,
     *     line: Number,
     *     column: Number
     *   }
     * })|null|!Object}
     */
    _getNormalizedRange(selection) {
      const rangeCount = selection.rangeCount;
      if (rangeCount === 0) {
        return null;
      } else if (rangeCount === 1) {
        return this._normalizeRange(selection.getRangeAt(0));
      } else {
        const startRange = this._normalizeRange(selection.getRangeAt(0));
        const endRange = this._normalizeRange(
            selection.getRangeAt(rangeCount - 1));
        return {
          start: startRange.start,
          end: endRange.end,
        };
      }
    },

    /**
     * Normalize a specific DOM Range.
     * @return {!Object} fixed normalized range
     */
    _normalizeRange(domRange) {
      const range = GrRangeNormalizer.normalize(domRange);
      return this._fixTripleClickSelection({
        start: this._normalizeSelectionSide(
            range.startContainer, range.startOffset),
        end: this._normalizeSelectionSide(
            range.endContainer, range.endOffset),
      }, domRange);
    },

    /**
     * Adjust triple click selection for the whole line.
     * A triple click always results in:
     * - start.column == end.column == 0
     * - end.line == start.line + 1
     *
     * @param {!Object} range Normalized range, ie column/line numbers
     * @param {!Range} domRange DOM Range object
     * @return {!Object} fixed normalized range
     */
    _fixTripleClickSelection(range, domRange) {
      if (!range.start) {
        // Selection outside of current diff.
        return range;
      }
      const start = range.start;
      const end = range.end;
      // Happens when triple click in side-by-side mode with other side empty.
      const endsAtOtherEmptySide = !end &&
          domRange.endOffset === 0 &&
          domRange.endContainer.nodeName === 'TD' &&
          (domRange.endContainer.classList.contains('left') ||
           domRange.endContainer.classList.contains('right'));
      const endsAtBeginningOfNextLine = end &&
          start.column === 0 &&
          end.column === 0 &&
          end.line === start.line + 1;
      const content = domRange.cloneContents().querySelector('.contentText');
      const lineLength = content && this._getLength(content) || 0;
      if (lineLength && (endsAtBeginningOfNextLine || endsAtOtherEmptySide)) {
        // Move the selection to the end of the previous line.
        range.end = {
          node: start.node,
          column: lineLength,
          side: start.side,
          line: start.line,
        };
      }
      return range;
    },

    /**
     * Convert DOM Range selection to concrete numbers (line, column, side).
     * Moves range end if it's not inside td.content.
     * Returns null if selection end is not valid (outside of diff).
     *
     * @param {Node} node td.content child
     * @param {number} offset offset within node
     * @return {({
     *   node: Node,
     *   side: string,
     *   line: Number,
     *   column: Number
     * }|undefined)}
     */
    _normalizeSelectionSide(node, offset) {
      let column;
      if (!this.contains(node)) {
        return;
      }
      const lineEl = this.diffBuilder.getLineElByChild(node);
      if (!lineEl) {
        return;
      }
      const side = this.diffBuilder.getSideByLineEl(lineEl);
      if (!side) {
        return;
      }
      const line = this.diffBuilder.getLineNumberByChild(lineEl);
      if (!line) {
        return;
      }
      const contentText = this.diffBuilder.getContentByLineEl(lineEl);
      if (!contentText) {
        return;
      }
      const contentTd = contentText.parentElement;
      if (!contentTd.contains(node)) {
        node = contentText;
        column = 0;
      } else {
        const thread = contentTd.querySelector('.comment-thread');
        if (thread && thread.contains(node)) {
          column = this._getLength(contentText);
          node = contentText;
        } else {
          column = this._convertOffsetToColumn(node, offset);
        }
      }

      return {
        node,
        side,
        line,
        column,
      };
    },

    /**
     * The only line in which add a comment tooltip is cut off is the first
     * line. Even if there is a collapsed section, The first visible line is
     * in the position where the second line would have been, if not for the
     * collapsed section, so don't need to worry about this case for
     * positioning the tooltip.
     */
    _positionActionBox(actionBox, startLine, range) {
      if (startLine > 1) {
        actionBox.placeAbove(range);
        return;
      }
      actionBox.positionBelow = true;
      actionBox.placeBelow(range);
    },

    _handleSelection(selection, isMouseUp) {
      const normalizedRange = this._getNormalizedRange(selection);
      if (!normalizedRange) {
        return;
      }
      const domRange = selection.getRangeAt(0);
      /** @type {?} */
      const start = normalizedRange.start;
      if (!start) {
        return;
      }
      const end = normalizedRange.end;
      if (!end) {
        return;
      }
      if (start.side !== end.side ||
          end.line < start.line ||
          (start.line === end.line && start.column === end.column)) {
        return;
      }

      // TODO (viktard): Drop empty first and last lines from selection.

      // If this was a mouse-up event, we create a comment immediately if
      // the selection is from the end of a line to the start of the next line.
      // Rather than trying to find the line contents, we just check if the
      // selection is empty to see that it's at the end of a line.
      // In this case, we select the entire start line.
      if (isMouseUp && start.line === end.line - 1 && end.column === 0) {
        const content = domRange.cloneContents().querySelector('.contentText');
        if (this._getLength(content) === 0) {
          this.fire('create-range-comment', {side: start.side, range: {
            start_line: start.line,
            start_character: 0,
            end_line: start.line,
            end_character: start.column,
          }});
          return;
        }
      }

      const actionBox = document.createElement('gr-selection-action-box');
      const root = Polymer.dom(this.root);
      root.insertBefore(actionBox, root.firstElementChild);
      actionBox.range = {
        start_line: start.line,
        start_character: start.column,
        end_line: end.line,
        end_character: end.column,
      };
      actionBox.side = start.side;
      if (start.line === end.line) {
        this._positionActionBox(actionBox, start.line, domRange);
      } else if (start.node instanceof Text) {
        if (start.column) {
          this._positionActionBox(actionBox, start.line,
              start.node.splitText(start.column));
        }
        start.node.parentElement.normalize(); // Undo splitText from above.
      } else if (start.node.classList.contains('content') &&
          start.node.firstChild) {
        this._positionActionBox(actionBox, start.line, start.node.firstChild);
      } else {
        this._positionActionBox(actionBox, start.line, start.node);
      }
    },

    _createRangeComment(e) {
      this._removeActionBox();
    },

    _removeActionBoxDebounced() {
      this.debounce('removeActionBox', this._removeActionBox, 10);
    },

    _removeActionBox() {
      const actionBox = this.$$('gr-selection-action-box');
      if (actionBox) {
        Polymer.dom(this.root).removeChild(actionBox);
      }
    },

    _convertOffsetToColumn(el, offset) {
      if (el instanceof Element && el.classList.contains('content')) {
        return offset;
      }
      while (el.previousSibling ||
          !el.parentElement.classList.contains('content')) {
        if (el.previousSibling) {
          el = el.previousSibling;
          offset += this._getLength(el);
        } else {
          el = el.parentElement;
        }
      }
      return offset;
    },

    /**
     * Traverse Element from right to left, call callback for each node.
     * Stops if callback returns true.
     *
     * @param {!Element} startNode
     * @param {function(Node):boolean} callback
     * @param {Object=} opt_flags If flags.left is true, traverse left.
     */
    _traverseContentSiblings(startNode, callback, opt_flags) {
      const travelLeft = opt_flags && opt_flags.left;
      let node = startNode;
      while (node) {
        if (node instanceof Element &&
            node.tagName !== 'HL' &&
            node.tagName !== 'SPAN') {
          break;
        }
        const nextNode = travelLeft ? node.previousSibling : node.nextSibling;
        if (callback(node)) {
          break;
        }
        node = nextNode;
      }
    },

    /**
     * Get length of a node. If the node is a content node, then only give the
     * length of its .contentText child.
     *
     * @param {?Element} node this is sometimes passed as null.
     * @return {number}
     */
    _getLength(node) {
      if (node instanceof Element && node.classList.contains('content')) {
        return this._getLength(node.querySelector('.contentText'));
      } else {
        return GrAnnotation.getLength(node);
      }
    },
  });
})();
