/**
 * @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.
 */
import '../../../styles/shared-styles.js';
import {addListener} from '@polymer/polymer/lib/utils/gestures.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {htmlTemplate} from './gr-diff-selection_html.js';
import {normalize} from '../gr-diff-highlight/gr-range-normalizer.js';
import {descendedFromClass, querySelectorAll} from '../../../utils/dom-util.js';

/**
 * 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',
  BLAME: 'selected-blame',
};

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

/**
 * @extends PolymerElement
 */
class GrDiffSelection extends GestureEventListeners(
    LegacyElementMixin(
        PolymerElement)) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-diff-selection'; }

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

  static get observers() {
    return [
      '_diffChanged(diff)',
    ];
  }

  /** @override */
  created() {
    super.created();
    this.addEventListener('copy',
        e => this._handleCopy(e));
    addListener(this, 'down',
        e => this._handleDown(e));
  }

  /** @override */
  attached() {
    super.attached();
    this.classList.add(SelectionClass.RIGHT);
  }

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

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

  _handleDownOnRangeComment(node) {
    if (node &&
        node.nodeName &&
        node.nodeName.toLowerCase() === 'gr-comment-thread') {
      this._setClasses([
        SelectionClass.COMMENT,
        node.commentSide === 'left' ?
          SelectionClass.LEFT :
          SelectionClass.RIGHT,
      ]);
      return true;
    }
    return false;
  }

  _handleDown(e) {
    // Handle the down event on comment thread in Polymer 2
    const handled = this._handleDownOnRangeComment(e.target);
    if (handled) return;

    const lineEl = this.diffBuilder.getLineElByChild(e.target);
    const blameSelected = this._elementDescendedFromClass(e.target, 'blame');
    if (!lineEl && !blameSelected) { return; }

    const targetClasses = [];

    if (blameSelected) {
      targetClasses.push(SelectionClass.BLAME);
    } else {
      const commentSelected =
          this._elementDescendedFromClass(e.target, 'gr-comment');
      const side = this.diffBuilder.getSideByLineEl(lineEl);

      targetClasses.push(side === 'left' ?
        SelectionClass.LEFT :
        SelectionClass.RIGHT);

      if (commentSelected) {
        targetClasses.push(SelectionClass.COMMENT);
      }
    }

    this._setClasses(targetClasses);
  }

  /**
   * Set the provided list of classes on the element, to the exclusion of all
   * other SelectionClass values.
   *
   * @param {!Array<!string>} targetClasses
   */
  _setClasses(targetClasses) {
    // 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 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) {
    return descendedFromClass(element, className,
        this.diffBuilder.diffElement);
  }

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

  _getSelection() {
    const diffHosts = querySelectorAll(document.body, 'gr-diff');
    if (!diffHosts.length) return window.getSelection();

    const curDiffHost = diffHosts.find(diffHost => {
      if (!diffHost || !diffHost.shadowRoot) return false;
      const selection = diffHost.shadowRoot.getSelection();
      // Pick the one with valid selection:
      // https://developer.mozilla.org/en-US/docs/Web/API/Selection/type
      return selection && selection.type !== 'None';
    });

    return curDiffHost ?
      curDiffHost.shadowRoot.getSelection(): window.getSelection();
  }

  /**
   * Get the text of the current 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 = this._getSelection();
    if (sel.rangeCount != 1) {
      return ''; // No multi-select support yet.
    }
    if (commentSelected) {
      return this._getCommentLines(sel, side);
    }
    const range = normalize(sel.getRangeAt(0));
    const startLineEl =
        this.diffBuilder.getLineElByChild(range.startContainer);
    const endLineEl = this.diffBuilder.getLineElByChild(range.endContainer);
    // Happens when triple click in side-by-side mode with other side empty.
    const endsAtOtherEmptySide = !endLineEl &&
        range.endOffset === 0 &&
        range.endContainer.nodeName === 'TD' &&
        (range.endContainer.classList.contains('left') ||
         range.endContainer.classList.contains('right'));
    const startLineNum = parseInt(startLineEl.getAttribute('data-value'), 10);
    let endLineNum;
    if (endsAtOtherEmptySide) {
      endLineNum = startLineNum + 1;
    } else if (endLineEl) {
      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|undefined} endLineNum Use undefined to get the range
   *     extending to the end of the file.
   * @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 = 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;
  }
}

customElements.define(GrDiffSelection.is, GrDiffSelection);
