/**
 * @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.
 */
(function() {
  'use strict';

  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 Polymer.mixinBehaviors([Gerrit.FireBehavior],
      Polymer.GestureEventListeners(
          Polymer.LegacyElementMixin(Polymer.Element))) {
    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,
      };
    }

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

    /** @override */
    ready() {
      super.ready();
      Polymer.RenderStatus.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.fire('ready', null, {bubbles: false});
      });
    }

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

    /** @override */
    detached() {
      super.detached();
      this.unlisten(window, 'scroll', '_handleWindowScroll');
    }

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

    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 = Polymer.dom(/** @type {Node} */ (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();
    }

    reInitCursor() {
      this._updateStops();
      if (this.initialLineNumber) {
        this.moveToLineNumber(this.initialLineNumber, this.side);
        this.initialLineNumber = null;
      } else {
        this.moveToFirstChunk();
      }
    }

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

    handleDiffUpdate() {
      this._updateStops();
      if (!this.diffRow) {
        // does not scroll during init unless requested
        const scrollingBehaviorForInit = this.initialLineNumber ?
          ScrollBehavior.KEEP_VISIBLE :
          ScrollBehavior.NEVER;
        this._scrollBehavior = scrollingBehaviorForInit;
        this.reInitCursor();
      }
      this._scrollBehavior = ScrollBehavior.KEEP_VISIBLE;
      this._focusOnMove = true;
      this._listeningForScroll = false;
    }

    _handleDiffRenderStart() {
      this._listeningForScroll = true;
    }

    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.listen(this.diffs[i], 'render-start', '_handleDiffRenderStart');
          this.listen(this.diffs[i], 'render-content', 'handleDiffUpdate');
        }

        for (i = 0;
          i < splice.removed && splice.removed.length;
          i++) {
          this.unlisten(splice.removed[i],
              'render-start', '_handleDiffRenderStart');
          this.unlisten(splice.removed[i],
              'render-content', 'handleDiffUpdate');
        }
      }
    }

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