/**
 * @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,
    },

    behaviors: [
      Gerrit.FireBehavior,
    ],

    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,
     *     because isMouseUp === true combined with an existing selection must
     *     mean that this is the end of a double-click.
     */
    handleSelectionChange(selection, isMouseUp) {
      // Debounce is not just nice for waiting until the selection has settled,
      // it is also vital for being able to click on the action box before it is
      // removed.
      // If you wait longer than 50 ms, then you don't properly catch a very
      // quick 'c' press after the selection change. If you wait less than 10
      // ms, then you will have about 50 _handleSelection calls when doing a
      // simple drag for select.
      this.debounce(
          'selectionChange', () => this._handleSelection(selection, isMouseUp),
          10);
    },

    _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) {
      /* On Safari the ShadowRoot.getSelection() isn't there and the only thing
         we can get is a single Range */
      if (selection instanceof Range) {
        return this._normalizeRange(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);
    },

    _isRangeValid(range) {
      if (!range || !range.start || !range.end) {
        return false;
      }
      const start = range.start;
      const end = range.end;
      if (start.side !== end.side ||
          end.line < start.line ||
          (start.line === end.line && start.column === end.column)) {
        return false;
      }
      return true;
    },

    _handleSelection(selection, isMouseUp) {
      /* On Safari, the selection events may return a null range that should
         be ignored */
      if (!selection) {
        return;
      }
      const normalizedRange = this._getNormalizedRange(selection);
      if (!this._isRangeValid(normalizedRange)) {
        this._removeActionBox();
        return;
      }
      /* On Safari the ShadowRoot.getSelection() isn't there and the only thing
         we can get is a single Range */
      const domRange = selection instanceof Range ? selection:selection.getRangeAt(0);
      const start = normalizedRange.start;
      const end = normalizedRange.end;

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

      // If the selection is from the end of one line to the start of the next
      // line, then this must have been a double-click, or you have started
      // dragging. Showing the action box is bad in the former case and not very
      // useful in the latter, so never do that.
      // 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.
      // In a perfect world we would only do this for double-click, but it is
      // extremely rare that a user would drag from the end of one line to the
      // start of the next and release the mouse, so we don't bother.
      // TODO(brohlfs): This does not work, if the double-click is before a new
      // diff chunk (start will be equal to end), and neither before an "expand
      // the diff context" block (end line will match the first line of the new
      // section and thus be greater than start line + 1).
      if (start.line === end.line - 1 && end.column === 0) {
        // Rather than trying to find the line contents (for comparing
        // start.column with the content length), we just check if the selection
        // is empty to see that it's at the end of a line.
        const content = domRange.cloneContents().querySelector('.contentText');
        if (isMouseUp && 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;
      }

      let actionBox = this.$$('gr-selection-action-box');
      if (!actionBox) {
        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();
    },

    _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);
      }
    },
  });
})();
