// 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';

  /**
   * Possible CSS classes indicating the state of selection. Dynamically added/
   * removed based on where the user clicks within the diff.
   */
  const SelectionClass = {
    COMMENT: 'selected-comment',
    LEFT: 'selected-left',
    RIGHT: 'selected-right',
  };

  const getNewCache = () => { return {left: null, right: null}; };

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

    properties: {
      diff: Object,
      /** @type {?Object} */
      _cachedDiffBuilder: Object,
      _linesCache: {
        type: Object,
        value: getNewCache(),
      },
    },

    observers: [
      '_diffChanged(diff)',
    ],

    listeners: {
      copy: '_handleCopy',
      down: '_handleDown',
    },

    attached() {
      this.classList.add(SelectionClass.RIGHT);
    },

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

    _diffChanged() {
      this._linesCache = getNewCache();
    },

    _handleDown(e) {
      const lineEl = this.diffBuilder.getLineElByChild(e.target);
      if (!lineEl) {
        return;
      }
      const commentSelected =
          this._elementDescendedFromClass(e.target, 'gr-diff-comment');
      const side = this.diffBuilder.getSideByLineEl(lineEl);
      const targetClasses = [];
      targetClasses.push(side === 'left' ?
          SelectionClass.LEFT :
          SelectionClass.RIGHT);

      if (commentSelected) {
        targetClasses.push(SelectionClass.COMMENT);
      }
      // Remove any selection classes that do not belong.
      for (const key in SelectionClass) {
        if (SelectionClass.hasOwnProperty(key)) {
          const className = SelectionClass[key];
          if (!targetClasses.includes(className)) {
            this.classList.remove(SelectionClass[key]);
          }
        }
      }
      // Add new selection classes iff they are not already present.
      for (const _class of targetClasses) {
        if (!this.classList.contains(_class)) {
          this.classList.add(_class);
        }
      }
    },

    _getCopyEventTarget(e) {
      return Polymer.dom(e).rootTarget;
    },

    /**
     * Utility function to determine whether an element is a descendant of
     * another element with the particular className.
     *
     * @param {!Element} element
     * @param {!string} className
     * @return {boolean}
     */
    _elementDescendedFromClass(element, className) {
      while (!element.classList.contains(className)) {
        if (!element.parentElement ||
            element === this.diffBuilder.diffElement) {
          return false;
        }
        element = element.parentElement;
      }
      return true;
    },

    _handleCopy(e) {
      let commentSelected = false;
      const target = this._getCopyEventTarget(e);
      if (target.type === 'textarea') { return; }
      if (!this._elementDescendedFromClass(target, 'diff-row')) { return; }
      if (this.classList.contains(SelectionClass.COMMENT)) {
        commentSelected = true;
      }
      const lineEl = this.diffBuilder.getLineElByChild(target);
      if (!lineEl) {
        return;
      }
      const side = this.diffBuilder.getSideByLineEl(lineEl);
      const text = this._getSelectedText(side, commentSelected);
      if (text) {
        e.clipboardData.setData('Text', text);
        e.preventDefault();
      }
    },

    /**
     * Get the text of the current window selection. If commentSelected is
     * true, it returns only the text of comments within the selection.
     * Otherwise it returns the text of the selected diff region.
     *
     * @param {!string} side The side that is selected.
     * @param {boolean} commentSelected Whether or not a comment is selected.
     * @return {string} The selected text.
     */
    _getSelectedText(side, commentSelected) {
      const sel = window.getSelection();
      if (sel.rangeCount != 1) {
        return ''; // No multi-select support yet.
      }
      if (commentSelected) {
        return this._getCommentLines(sel, side);
      }
      const range = GrRangeNormalizer.normalize(sel.getRangeAt(0));
      const startLineEl =
          this.diffBuilder.getLineElByChild(range.startContainer);
      const endLineEl = this.diffBuilder.getLineElByChild(range.endContainer);
      const startLineNum = parseInt(startLineEl.getAttribute('data-value'), 10);
      const endLineNum = parseInt(endLineEl.getAttribute('data-value'), 10);

      return this._getRangeFromDiff(startLineNum, range.startOffset, endLineNum,
          range.endOffset, side);
    },

    /**
     * Query the diff object for the selected lines.
     *
     * @param {number} startLineNum
     * @param {number} startOffset
     * @param {number} endLineNum
     * @param {number} endOffset
     * @param {!string} side The side that is currently selected.
     * @return {string} The selected diff text.
     */
    _getRangeFromDiff(startLineNum, startOffset, endLineNum, endOffset, side) {
      const lines =
          this._getDiffLines(side).slice(startLineNum - 1, endLineNum);
      if (lines.length) {
        lines[lines.length - 1] = lines[lines.length - 1]
            .substring(0, endOffset);
        lines[0] = lines[0].substring(startOffset);
      }
      return lines.join('\n');
    },

    /**
     * Query the diff object for the lines from a particular side.
     *
     * @param {!string} side The side that is currently selected.
     * @return {!Array<string>} An array of strings indexed by line number.
     */
    _getDiffLines(side) {
      if (this._linesCache[side]) {
        return this._linesCache[side];
      }
      let lines = [];
      const key = side === 'left' ? 'a' : 'b';
      for (const chunk of this.diff.content) {
        if (chunk.ab) {
          lines = lines.concat(chunk.ab);
        } else if (chunk[key]) {
          lines = lines.concat(chunk[key]);
        }
      }
      this._linesCache[side] = lines;
      return lines;
    },

    /**
     * Query the diffElement for comments and check whether they lie inside the
     * selection range.
     *
     * @param {!Selection} sel The selection of the window.
     * @param {!string} side The side that is currently selected.
     * @return {string} The selected comment text.
     */
    _getCommentLines(sel, side) {
      const range = GrRangeNormalizer.normalize(sel.getRangeAt(0));
      const content = [];
      // Query the diffElement for comments.
      const messages = this.diffBuilder.diffElement.querySelectorAll(
          `.side-by-side [data-side="${side
          }"] .message *, .unified .message *`);

      for (let i = 0; i < messages.length; i++) {
        const el = messages[i];
        // Check if the comment element exists inside the selection.
        if (sel.containsNode(el, true)) {
          // Padded elements require newlines for accurate spacing.
          if (el.parentElement.id === 'container' ||
              el.parentElement.nodeName === 'BLOCKQUOTE') {
            if (content.length && content[content.length - 1] !== '') {
              content.push('');
            }
          }

          if (el.id === 'output' &&
              !this._elementDescendedFromClass(el, 'collapsed')) {
            content.push(this._getTextContentForRange(el, sel, range));
          }
        }
      }

      return content.join('\n');
    },

    /**
     * Given a DOM node, a selection, and a selection range, recursively get all
     * of the text content within that selection.
     * Using a domNode that isn't in the selection returns an empty string.
     *
     * @param {!Node} domNode The root DOM node.
     * @param {!Selection} sel The selection.
     * @param {!Range} range The normalized selection range.
     * @return {string} The text within the selection.
     */
    _getTextContentForRange(domNode, sel, range) {
      if (!sel.containsNode(domNode, true)) { return ''; }

      let text = '';
      if (domNode instanceof Text) {
        text = domNode.textContent;
        if (domNode === range.endContainer) {
          text = text.substring(0, range.endOffset);
        }
        if (domNode === range.startContainer) {
          text = text.substring(range.startOffset);
        }
      } else {
        for (const childNode of domNode.childNodes) {
          text += this._getTextContentForRange(childNode, sel, range);
        }
      }
      return text;
    },
  });
})();
