/**
 * @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';
import {addListener} from '@polymer/polymer/lib/utils/gestures';
import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-diff-selection_html';
import {
  normalize,
  NormalizedRange,
} from '../gr-diff-highlight/gr-range-normalizer';
import {descendedFromClass, querySelectorAll} from '../../../utils/dom-util';
import {customElement, property, observe} from '@polymer/decorators';
import {DiffInfo} from '../../../types/diff';
import {Side} from '../../../constants/constants';
import {GrDiffBuilderElement} from '../gr-diff-builder/gr-diff-builder-element';
import {getSide, isThreadEl} from '../gr-diff/gr-diff-utils';

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

interface LinesCache {
  left: string[] | null;
  right: string[] | null;
}

function getNewCache(): LinesCache {
  return {left: null, right: null};
}

@customElement('gr-diff-selection')
export class GrDiffSelection extends PolymerElement {
  static get template() {
    return htmlTemplate;
  }

  @property({type: Object})
  diff?: DiffInfo;

  @property({type: Object})
  _cachedDiffBuilder?: GrDiffBuilderElement;

  @property({type: Object})
  _linesCache: LinesCache = {left: null, right: null};

  constructor() {
    super();
    this.addEventListener('copy', e => this._handleCopy(e));
    addListener(this, 'down', e => this._handleDown(e));
  }

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

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

  @observe('diff')
  _diffChanged() {
    this._linesCache = getNewCache();
  }

  _handleDownOnRangeComment(node: Element) {
    if (isThreadEl(node)) {
      this._setClasses([
        SelectionClass.COMMENT,
        getSide(node) === Side.LEFT
          ? SelectionClass.LEFT
          : SelectionClass.RIGHT,
      ]);
      return true;
    }
    return false;
  }

  _handleDown(e: Event) {
    const target = e.target;
    if (!(target instanceof Element)) return;
    // Handle the down event on comment thread in Polymer 2
    const handled = this._handleDownOnRangeComment(target);
    if (handled) return;
    const lineEl = this.diffBuilder.getLineElByChild(target);
    const blameSelected = this._elementDescendedFromClass(target, 'blame');
    if (!lineEl && !blameSelected) {
      return;
    }

    const targetClasses = [];

    if (blameSelected) {
      targetClasses.push(SelectionClass.BLAME);
    } else if (lineEl) {
      const commentSelected = this._elementDescendedFromClass(
        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.
   */
  _setClasses(targetClasses: string[]) {
    // Remove any selection classes that do not belong.
    for (const className of Object.values(SelectionClass)) {
      if (!targetClasses.includes(className)) {
        this.classList.remove(className);
      }
    }
    // 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: Event) {
    return (dom(e) as EventApi).rootTarget;
  }

  /**
   * Utility function to determine whether an element is a descendant of
   * another element with the particular className.
   */
  _elementDescendedFromClass(element: Element, className: string) {
    return descendedFromClass(element, className, this.diffBuilder.diffElement);
  }

  _handleCopy(e: ClipboardEvent) {
    let commentSelected = false;
    const target = this._getCopyEventTarget(e);
    if (!(target instanceof Element)) return;
    if (target instanceof HTMLTextAreaElement) 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) {
      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?.shadowRoot?.getSelection) 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 side The side that is selected.
   * @param commentSelected Whether or not a comment is selected.
   * @return The selected text.
   */
  _getSelectedText(side: Side, commentSelected: boolean) {
    const sel = this._getSelection();
    if (!sel || 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);
    if (!startLineEl) return;
    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 instanceof HTMLTableCellElement &&
      (range.endContainer.classList.contains('left') ||
        range.endContainer.classList.contains('right'));
    const startLineDataValue = startLineEl.getAttribute('data-value');
    if (!startLineDataValue) return;
    const startLineNum = Number(startLineDataValue);
    let endLineNum;
    if (endsAtOtherEmptySide) {
      endLineNum = startLineNum + 1;
    } else if (endLineEl) {
      const endLineDataValue = endLineEl.getAttribute('data-value');
      if (endLineDataValue) endLineNum = Number(endLineDataValue);
    }

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

  /**
   * Query the diff object for the selected lines.
   */
  _getRangeFromDiff(
    startLineNum: number,
    startOffset: number,
    endLineNum: number | undefined,
    endOffset: number,
    side: 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 side The side that is currently selected.
   * @return An array of strings indexed by line number.
   */
  _getDiffLines(side: Side): string[] {
    if (this._linesCache[side]) {
      return this._linesCache[side]!;
    }
    if (!this.diff) return [];
    let lines: string[] = [];
    for (const chunk of this.diff.content) {
      if (chunk.ab) {
        lines = lines.concat(chunk.ab);
      } else if (side === Side.LEFT && chunk.a) {
        lines = lines.concat(chunk.a);
      } else if (side === Side.RIGHT && chunk.b) {
        lines = lines.concat(chunk.b);
      }
    }
    this._linesCache[side] = lines;
    return lines;
  }

  /**
   * Query the diffElement for comments and check whether they lie inside the
   * selection range.
   *
   * @param sel The selection of the window.
   * @param side The side that is currently selected.
   * @return The selected comment text.
   */
  _getCommentLines(sel: Selection, side: 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 domNode The root DOM node.
   * @param sel The selection.
   * @param range The normalized selection range.
   * @return The text within the selection.
   */
  _getTextContentForRange(
    domNode: Node,
    sel: Selection,
    range: NormalizedRange
  ) {
    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;
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-diff-selection': GrDiffSelection;
  }
}
