/**
 * @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 '../../../scripts/bundled-polymer.js';

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 {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.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 {DomUtilBehavior} from '../../../behaviors/dom-util-behavior/dom-util-behavior.js';
import {GrRangeNormalizer} from '../gr-diff-highlight/gr-range-normalizer.js';
import {util} from '../../../scripts/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 Polymer.Element
 */
class GrDiffSelection extends mixinBehaviors( [
  DomUtilBehavior,
], 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 this.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 = util.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 = GrRangeNormalizer.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 = 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;
  }
}

customElements.define(GrDiffSelection.is, GrDiffSelection);
