/**
 * @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 '../../shared/gr-cursor-manager/gr-cursor-manager.js';
import {afterNextRender} from '@polymer/polymer/lib/utils/render-status.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-cursor_html.js';

const DiffSides = {
  LEFT: 'left',
  RIGHT: 'right',
};

const DiffViewMode = {
  SIDE_BY_SIDE: 'SIDE_BY_SIDE',
  UNIFIED: 'UNIFIED_DIFF',
};

const ScrollBehavior = {
  KEEP_VISIBLE: 'keep-visible',
  NEVER: 'never',
};

const LEFT_SIDE_CLASS = 'target-side-left';
const RIGHT_SIDE_CLASS = 'target-side-right';

/** @extends Polymer.Element */
class GrDiffCursor extends GestureEventListeners(
    LegacyElementMixin(PolymerElement)) {
  static get template() { return htmlTemplate; }

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

  static get properties() {
    return {
    /**
     * Either DiffSides.LEFT or DiffSides.RIGHT.
     */
      side: {
        type: String,
        value: DiffSides.RIGHT,
      },
      /** @type {!HTMLElement|undefined} */
      diffRow: {
        type: Object,
        notify: true,
        observer: '_rowChanged',
      },

      /**
       * The diff views to cursor through and listen to.
       */
      diffs: {
        type: Array,
        value() { return []; },
      },

      /**
       * If set, the cursor will attempt to move to the line number (instead of
       * the first chunk) the next time the diff renders. It is set back to null
       * when used. It should be only used if you want the line to be focused
       * after initialization of the component and page should scroll
       * to that position. This parameter should be set at most for one gr-diff
       * element in the page.
       *
       * @type {?number}
       */
      initialLineNumber: {
        type: Number,
        value: null,
      },

      /**
       * The scroll behavior for the cursor. Values are 'never' and
       * 'keep-visible'. 'keep-visible' will only scroll if the cursor is beyond
       * the viewport.
       */
      _scrollBehavior: {
        type: String,
        value: ScrollBehavior.KEEP_VISIBLE,
      },

      _focusOnMove: {
        type: Boolean,
        value: true,
      },

      _listeningForScroll: Boolean,

      /**
       * gr-diff-view has gr-fixed-panel on top. The panel can
       * intersect a main element and partially hides a content of
       * the main element. To correctly calculates visibility of an
       * element, the cursor must know how much height occuped by a fixed
       * panel.
       * The scrollTopMargin defines margin occuped by fixed panel.
       */
      scrollTopMargin: {
        type: Number,
        value: 0,
      },
    };
  }

  static get observers() {
    return [
      '_updateSideClass(side)',
      '_diffsChanged(diffs.splices)',
    ];
  }

  constructor() {
    super();
    this._boundHandleWindowScroll = () => this._handleWindowScroll();
    this._boundHandleDiffRenderStart = () => this._handleDiffRenderStart();
    this._boundHandleDiffRenderContent = () => this._handleDiffRenderContent();
    this._boundHandleDiffLineSelected = e => this._handleDiffLineSelected(e);
  }

  /** @override */
  ready() {
    super.ready();
    afterNextRender(this, () => {
      /*
      This represents the diff cursor is ready for interaction coming from
      client components. It is more then Polymer "ready" lifecycle, as no
      "ready" events are automatically fired by Polymer, it means
      the cursor is completely interactable - in this case attached and
      painted on the page. We name it "ready" instead of "rendered" as the
      long-term goal is to make gr-diff-cursor a javascript class - not a DOM
      element with an actual lifecycle. This will be triggered only once
      per element.
      */
      this.dispatchEvent(new CustomEvent('ready', {
        composed: true, bubbles: false,
      }));
    });
  }

  /** @override */
  connectedCallback() {
    super.connectedCallback();
    // Catch when users are scrolling as the view loads.
    window.addEventListener('scroll', this._boundHandleWindowScroll);
  }

  /** @override */
  disconnectedCallback() {
    super.disconnectedCallback();
    window.removeEventListener('scroll', this._boundHandleWindowScroll);
  }

  moveLeft() {
    this.side = DiffSides.LEFT;
    if (this._isTargetBlank()) {
      this.moveUp();
    }
  }

  moveRight() {
    this.side = DiffSides.RIGHT;
    if (this._isTargetBlank()) {
      this.moveUp();
    }
  }

  moveDown() {
    if (this._getViewMode() === DiffViewMode.SIDE_BY_SIDE) {
      this.$.cursorManager.next(this._rowHasSide.bind(this));
    } else {
      this.$.cursorManager.next();
    }
  }

  moveUp() {
    if (this._getViewMode() === DiffViewMode.SIDE_BY_SIDE) {
      this.$.cursorManager.previous(this._rowHasSide.bind(this));
    } else {
      this.$.cursorManager.previous();
    }
  }

  moveToVisibleArea() {
    if (this._getViewMode() === DiffViewMode.SIDE_BY_SIDE) {
      this.$.cursorManager.moveToVisibleArea(
          this._rowHasSide.bind(this));
    } else {
      this.$.cursorManager.moveToVisibleArea();
    }
  }

  moveToNextChunk(opt_clipToTop) {
    this.$.cursorManager.next(this._isFirstRowOfChunk.bind(this),
        target => target.parentNode.scrollHeight, opt_clipToTop);
    this._fixSide();
  }

  moveToPreviousChunk() {
    this.$.cursorManager.previous(this._isFirstRowOfChunk.bind(this));
    this._fixSide();
  }

  moveToNextCommentThread() {
    this.$.cursorManager.next(this._rowHasThread.bind(this));
    this._fixSide();
  }

  moveToPreviousCommentThread() {
    this.$.cursorManager.previous(this._rowHasThread.bind(this));
    this._fixSide();
  }

  /**
   * @param {number} number
   * @param {string} side
   * @param {string=} opt_path
   */
  moveToLineNumber(number, side, opt_path) {
    const row = this._findRowByNumberAndFile(number, side, opt_path);
    if (row) {
      this.side = side;
      this.$.cursorManager.setCursor(row);
    }
  }

  /**
   * Get the line number element targeted by the cursor row and side.
   *
   * @return {?Element|undefined}
   */
  getTargetLineElement() {
    let lineElSelector = '.lineNum';

    if (!this.diffRow) {
      return;
    }

    if (this._getViewMode() === DiffViewMode.SIDE_BY_SIDE) {
      lineElSelector += this.side === DiffSides.LEFT ? '.left' : '.right';
    }

    return this.diffRow.querySelector(lineElSelector);
  }

  getTargetDiffElement() {
    if (!this.diffRow) return null;

    const hostOwner = dom( (this.diffRow))
        .getOwnerRoot();
    if (hostOwner && hostOwner.host &&
        hostOwner.host.tagName === 'GR-DIFF') {
      return hostOwner.host;
    }
    return null;
  }

  moveToFirstChunk() {
    this.$.cursorManager.moveToStart();
    this.moveToNextChunk(true);
  }

  moveToLastChunk() {
    this.$.cursorManager.moveToEnd();
    this.moveToPreviousChunk();
  }

  /**
   * Move the cursor either to initialLineNumber or the first chunk and
   * reset scroll behavior.
   *
   * This may grab the focus from the app.
   *
   * If you do not want to move the cursor or grab focus, and just want to
   * reset the scroll behavior, use reInit() instead.
   */
  reInitCursor() {
    if (!this.diffRow) {
      // does not scroll during init unless requested
      const scrollingBehaviorForInit = this.initialLineNumber ?
        ScrollBehavior.KEEP_VISIBLE :
        ScrollBehavior.NEVER;
      this._scrollBehavior = scrollingBehaviorForInit;
      if (this.initialLineNumber) {
        this.moveToLineNumber(this.initialLineNumber, this.side);
        this.initialLineNumber = null;
      } else {
        this.moveToFirstChunk();
      }
    }
    this.reInit();
  }

  reInit() {
    this._scrollBehavior = ScrollBehavior.KEEP_VISIBLE;
  }

  _handleWindowScroll() {
    if (this._preventAutoScrollOnManualScroll) {
      this._scrollBehavior = ScrollBehavior.NEVER;
      this._focusOnMove = false;
      this._preventAutoScrollOnManualScroll = false;
    }
  }

  handleDiffUpdate() {
    this._updateStops();
    this.reInitCursor();
  }

  _handleDiffRenderStart() {
    this._preventAutoScrollOnManualScroll = true;
  }

  _handleDiffRenderContent() {
    this._updateStops();
    // When done rendering, turn focus on move and automatic scrolling back on
    this._focusOnMove = true;
    this._preventAutoScrollOnManualScroll = false;
  }

  _handleDiffLineSelected(event) {
    this.moveToLineNumber(
        event.detail.number, event.detail.side, event.detail.path);
  }

  createCommentInPlace() {
    const diffWithRangeSelected = this.diffs
        .find(diff => diff.isRangeSelected());
    if (diffWithRangeSelected) {
      diffWithRangeSelected.createRangeComment();
    } else {
      const line = this.getTargetLineElement();
      if (line) {
        this.getTargetDiffElement().addDraftAtLine(line);
      }
    }
  }

  /**
   * Get an object describing the location of the cursor. Such as
   * {leftSide: false, number: 123} for line 123 of the revision, or
   * {leftSide: true, number: 321} for line 321 of the base patch.
   * Returns null if an address is not available.
   *
   * @return {?Object}
   */
  getAddress() {
    if (!this.diffRow) { return null; }

    // Get the line-number cell targeted by the cursor. If the mode is unified
    // then prefer the revision cell if available.
    let cell;
    if (this._getViewMode() === DiffViewMode.UNIFIED) {
      cell = this.diffRow.querySelector('.lineNum.right');
      if (!cell) {
        cell = this.diffRow.querySelector('.lineNum.left');
      }
    } else {
      cell = this.diffRow.querySelector('.lineNum.' + this.side);
    }
    if (!cell) { return null; }

    const number = cell.getAttribute('data-value');
    if (!number || number === 'FILE') { return null; }

    return {
      leftSide: cell.matches('.left'),
      number: parseInt(number, 10),
    };
  }

  _getViewMode() {
    if (!this.diffRow) {
      return null;
    }

    if (this.diffRow.classList.contains('side-by-side')) {
      return DiffViewMode.SIDE_BY_SIDE;
    } else {
      return DiffViewMode.UNIFIED;
    }
  }

  _rowHasSide(row) {
    const selector = (this.side === DiffSides.LEFT ? '.left' : '.right') +
        ' + .content';
    return !!row.querySelector(selector);
  }

  _isFirstRowOfChunk(row) {
    const parentClassList = row.parentNode.classList;
    return parentClassList.contains('section') &&
        parentClassList.contains('delta') &&
        !row.previousSibling;
  }

  _rowHasThread(row) {
    return row.querySelector('.thread-group');
  }

  /**
   * If we jumped to a row where there is no content on the current side then
   * switch to the alternate side.
   */
  _fixSide() {
    if (this._getViewMode() === DiffViewMode.SIDE_BY_SIDE &&
        this._isTargetBlank()) {
      this.side = this.side === DiffSides.LEFT ?
        DiffSides.RIGHT : DiffSides.LEFT;
    }
  }

  _isTargetBlank() {
    if (!this.diffRow) {
      return false;
    }

    const actions = this._getActionsForRow();
    return (this.side === DiffSides.LEFT && !actions.left) ||
        (this.side === DiffSides.RIGHT && !actions.right);
  }

  _rowChanged(newRow, oldRow) {
    if (oldRow) {
      oldRow.classList.remove(LEFT_SIDE_CLASS, RIGHT_SIDE_CLASS);
    }
    this._updateSideClass();
  }

  _updateSideClass() {
    if (!this.diffRow) {
      return;
    }
    this.toggleClass(LEFT_SIDE_CLASS, this.side === DiffSides.LEFT,
        this.diffRow);
    this.toggleClass(RIGHT_SIDE_CLASS, this.side === DiffSides.RIGHT,
        this.diffRow);
  }

  _isActionType(type) {
    return type !== 'blank' && type !== 'contextControl';
  }

  _getActionsForRow() {
    const actions = {left: false, right: false};
    if (this.diffRow) {
      actions.left = this._isActionType(
          this.diffRow.getAttribute('left-type'));
      actions.right = this._isActionType(
          this.diffRow.getAttribute('right-type'));
    }
    return actions;
  }

  _getStops() {
    return this.diffs.reduce(
        (stops, diff) => stops.concat(diff.getCursorStops()), []);
  }

  _updateStops() {
    this.$.cursorManager.stops = this._getStops();
  }

  /**
   * Setup and tear down on-render listeners for any diffs that are added or
   * removed from the cursor.
   *
   * @private
   */
  _diffsChanged(changeRecord) {
    if (!changeRecord) { return; }

    this._updateStops();

    let splice;
    let i;
    for (let spliceIdx = 0;
      changeRecord.indexSplices &&
          spliceIdx < changeRecord.indexSplices.length;
      spliceIdx++) {
      splice = changeRecord.indexSplices[spliceIdx];

      for (i = splice.index; i < splice.index + splice.addedCount; i++) {
        this.diffs[i].addEventListener(
            'render-start', this._boundHandleDiffRenderStart);
        this.diffs[i].addEventListener(
            'render-content', this._boundHandleDiffRenderContent);
        this.diffs[i].addEventListener(
            'line-selected', this._boundHandleDiffLineSelected);
      }

      for (i = 0; i < splice.removed && splice.removed.length; i++) {
        splice.removed[i].removeEventListener(
            'render-start', this._boundHandleDiffRenderStart);
        splice.removed[i].removeEventListener(
            'render-content', this._boundHandleDiffRenderContent);
        splice.removed[i].removeEventListener(
            'line-selected', this._boundHandleDiffLineSelected);
      }
    }
  }

  _findRowByNumberAndFile(targetNumber, side, opt_path) {
    let stops;
    if (opt_path) {
      const diff = this.diffs.filter(diff => diff.path === opt_path)[0];
      stops = diff.getCursorStops();
    } else {
      stops = this.$.cursorManager.stops;
    }
    let selector;
    for (let i = 0; i < stops.length; i++) {
      selector = '.lineNum.' + side + '[data-value="' + targetNumber + '"]';
      if (stops[i].querySelector(selector)) {
        return stops[i];
      }
    }
  }
}

customElements.define(GrDiffCursor.is, GrDiffCursor);
