/**
 * @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 {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-cursor-manager_html.js';
import {ScrollMode} from '../../../constants/constants.js';

// Time in which pressing n key again after the toast navigates to next file
const NAVIGATE_TO_NEXT_FILE_TIMEOUT_MS = 5000;

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

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

  static get properties() {
    return {
      stops: {
        type: Array,
        value() {
          return [];
        },
        observer: '_updateIndex',
      },
      /**
       * @type {?Object}
       */
      target: {
        type: Object,
        notify: true,
        observer: '_scrollToTarget',
      },
      /**
       * The height of content intended to be included with the target.
       *
       * @type {?number}
       */
      _targetHeight: Number,

      /**
       * The index of the current target (if any). -1 otherwise.
       */
      index: {
        type: Number,
        value: -1,
        notify: true,
      },

      /**
       * The class to apply to the current target. Use null for no class.
       */
      cursorTargetClass: {
        type: String,
        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.
       * TODO (beckysiegel) figure out why it can be undefined
       *
       * @type {string|undefined}
       */
      scrollMode: {
        type: String,
        value: ScrollMode.NEVER,
      },

      /**
       * When true, will call element.focus() during scrolling.
       */
      focusOnMove: {
        type: Boolean,
        value: false,
      },

      /**
       * The scrollTopMargin defines height of invisible area at the top
       * of the page. If cursor locates inside this margin - it is
       * not visible, because it is covered by some other element.
       */
      scrollTopMargin: {
        type: Number,
        value: 0,
      },
    };
  }

  /** @override */
  detached() {
    super.detached();
    this.unsetCursor();
  }

  /**
   * Move the cursor forward. Clipped to the ends of the stop list.
   *
   * @param {!Function=} opt_condition Optional stop condition. If a condition
   *    is passed the cursor will continue to move in the specified direction
   *    until the condition is met.
   * @param {!Function=} opt_getTargetHeight Optional function to calculate the
   *    height of the target's 'section'. The height of the target itself is
   *    sometimes different, used by the diff cursor.
   * @param {boolean=} opt_clipToTop When none of the next indices match, move
   *     back to first instead of to last.
   * @param {boolean=} opt_navigateToNextFile Navigate to next unreviewed file
   *     if user presses next on the last diff chunk
   * @private
   */

  next(opt_condition, opt_getTargetHeight, opt_clipToTop,
      opt_navigateToNextFile) {
    this._moveCursor(1, opt_condition, opt_getTargetHeight, opt_clipToTop,
        opt_navigateToNextFile);
  }

  previous(opt_condition) {
    this._moveCursor(-1, opt_condition);
  }

  /**
   * Move the cursor to the row which is the closest to the viewport center
   * in vertical direction.
   * The method uses IntersectionObservers API. If browser
   * doesn't support this API the method does nothing
   *
   * @param {!Function=} opt_condition Optional condition. If a condition
   *    is passed only stops which meet conditions are taken into account.
   */
  moveToVisibleArea(opt_condition) {
    if (!this.stops || !this._isIntersectionObserverSupported()) {
      return;
    }
    const filteredStops = opt_condition ? this.stops.filter(opt_condition)
      : this.stops;
    const dims = this._getWindowDims();
    const windowCenter =
        Math.round((dims.innerHeight + this.scrollTopMargin) / 2);

    let closestToTheCenter = null;
    let minDistanceToCenter = null;
    let unobservedCount = filteredStops.length;

    const observer = new IntersectionObserver(entries => {
      // This callback is called for the first time immediately.
      // Typically it gets all observed stops at once, but
      // sometimes can get them in several chunks.
      entries.forEach(entry => {
        observer.unobserve(entry.target);

        // In Edge it is recommended to use intersectionRatio instead of
        // isIntersecting.
        const isInsideViewport =
            entry.isIntersecting || entry.intersectionRatio > 0;
        if (!isInsideViewport) {
          return;
        }
        const center = entry.boundingClientRect.top + Math.round(
            entry.boundingClientRect.height / 2);
        const distanceToWindowCenter = Math.abs(center - windowCenter);
        if (minDistanceToCenter === null ||
            distanceToWindowCenter < minDistanceToCenter) {
          closestToTheCenter = entry.target;
          minDistanceToCenter = distanceToWindowCenter;
        }
      });
      unobservedCount -= entries.length;
      if (unobservedCount == 0 && closestToTheCenter) {
        // set cursor when all stops were observed.
        // In most cases the target is visible, so scroll is not
        // needed. But in rare cases the target can become invisible
        // at this point (due to some scrolling in window).
        // To avoid jumps set noScroll options.
        this.setCursor(closestToTheCenter, true);
      }
    });
    filteredStops.forEach(stop => {
      observer.observe(stop);
    });
  }

  _isIntersectionObserverSupported() {
    // The copy of this method exists in gr-app-element.js under the
    // name _isCursorManagerSupportMoveToVisibleLine
    // If you update this method, you must update gr-app-element.js
    // as well.
    return 'IntersectionObserver' in window;
  }

  /**
   * Set the cursor to an arbitrary element.
   *
   * @param {!HTMLElement} element
   * @param {boolean=} opt_noScroll prevent any potential scrolling in response
   *   setting the cursor.
   */
  setCursor(element, opt_noScroll) {
    let behavior;
    if (opt_noScroll) {
      behavior = this.scrollMode;
      this.scrollMode = ScrollMode.NEVER;
    }

    this.unsetCursor();
    this.target = element;
    this._updateIndex();
    this._decorateTarget();

    if (opt_noScroll) { this.scrollMode = behavior; }
  }

  unsetCursor() {
    this._unDecorateTarget();
    this.index = -1;
    this.target = null;
    this._targetHeight = null;
  }

  isAtStart() {
    return this.index === 0;
  }

  isAtEnd() {
    return this.index === this.stops.length - 1;
  }

  moveToStart() {
    if (this.stops.length) {
      this.setCursor(this.stops[0]);
    }
  }

  moveToEnd() {
    if (this.stops.length) {
      this.setCursor(this.stops[this.stops.length - 1]);
    }
  }

  setCursorAtIndex(index, opt_noScroll) {
    this.setCursor(this.stops[index], opt_noScroll);
  }

  /**
   * Move the cursor forward or backward by delta. Clipped to the beginning or
   * end of stop list.
   *
   * @param {number} delta either -1 or 1.
   * @param {!Function=} opt_condition Optional stop condition. If a condition
   *    is passed the cursor will continue to move in the specified direction
   *    until the condition is met.
   * @param {!Function=} opt_getTargetHeight Optional function to calculate the
   *    height of the target's 'section'. The height of the target itself is
   *    sometimes different, used by the diff cursor.
   * @param {boolean=} opt_clipToTop When none of the next indices match, move
   *     back to first instead of to last.
   * @param {boolean=} opt_navigateToNextFile Navigate to next unreviewed file
   *     if user presses next on the last diff chunk
   * @private
   */
  _moveCursor(delta, opt_condition, opt_getTargetHeight, opt_clipToTop,
      opt_navigateToNextFile) {
    if (!this.stops.length) {
      this.unsetCursor();
      return;
    }

    this._unDecorateTarget();

    const newIndex = this._getNextindex(delta, opt_condition, opt_clipToTop);

    let newTarget = null;
    if (newIndex !== -1) {
      newTarget = this.stops[newIndex];
    }

    /*
     * If user presses n on the last diff chunk, show a toast informing user
     * that pressing n again will navigate them to next unreviewed file.
     * If click happens within the time limit, then navigate to next file
     */
    if (opt_navigateToNextFile && this.index === newIndex) {
      if (newIndex === this.stops.length - 1) {
        if (this._lastDisplayedNavigateToNextFileToast && (Date.now() -
          this._lastDisplayedNavigateToNextFileToast <=
            NAVIGATE_TO_NEXT_FILE_TIMEOUT_MS)) {
          // reset for next file
          this._lastDisplayedNavigateToNextFileToast = null;
          this.dispatchEvent(new CustomEvent(
              'navigate-to-next-unreviewed-file', {
                composed: true, bubbles: true,
              }));
          return;
        }
        this._lastDisplayedNavigateToNextFileToast = Date.now();
        this.dispatchEvent(new CustomEvent('show-alert', {
          detail: {
            message: 'Press n again to navigate to next unreviewed file',
          },
          composed: true, bubbles: true,
        }));
        return;
      }
    }

    this.index = newIndex;
    this.target = newTarget;

    if (!this.target) { return; }

    if (opt_getTargetHeight) {
      this._targetHeight = opt_getTargetHeight(newTarget);
    } else {
      this._targetHeight = newTarget.scrollHeight;
    }

    if (this.focusOnMove) { this.target.focus(); }

    this._decorateTarget();
  }

  _decorateTarget() {
    if (this.target && this.cursorTargetClass) {
      this.target.classList.add(this.cursorTargetClass);
    }
  }

  _unDecorateTarget() {
    if (this.target && this.cursorTargetClass) {
      this.target.classList.remove(this.cursorTargetClass);
    }
  }

  /**
   * Get the next stop index indicated by the delta direction.
   *
   * @param {number} delta either -1 or 1.
   * @param {!Function=} opt_condition Optional stop condition.
   * @param {boolean=} opt_clipToTop When none of the next indices match, move
   *     back to first instead of to last.
   * @return {number} the new index.
   * @private
   */
  _getNextindex(delta, opt_condition, opt_clipToTop) {
    if (!this.stops.length) {
      return -1;
    }
    let newIndex = this.index;
    // If the cursor is not yet set and we are going backwards, start at the
    // back.
    if (this.index === -1 && delta < 0) {
      newIndex = this.stops.length;
    }
    do {
      newIndex = newIndex + delta;
    } while ((delta > 0 || newIndex > 0) &&
             (delta < 0 || newIndex < this.stops.length - 1) &&
             opt_condition && !opt_condition(this.stops[newIndex]));

    newIndex = Math.max(0, Math.min(this.stops.length - 1, newIndex));

    // If we failed to satisfy the condition:
    if (opt_condition && !opt_condition(this.stops[newIndex])) {
      if (delta < 0 || opt_clipToTop) {
        return 0;
      } else if (delta > 0) {
        return this.stops.length - 1;
      }
      return this.index;
    }

    return newIndex;
  }

  _updateIndex() {
    if (!this.target) {
      this.index = -1;
      return;
    }

    const newIndex = Array.prototype.indexOf.call(this.stops, this.target);
    if (newIndex === -1) {
      this.unsetCursor();
    } else {
      this.index = newIndex;
    }
  }

  /**
   * Calculate where the element is relative to the window.
   *
   * @param {!Object} target Target to scroll to.
   * @return {number} Distance to top of the target.
   */
  _getTop(target) {
    let top = target.offsetTop;
    for (let offsetParent = target.offsetParent;
      offsetParent;
      offsetParent = offsetParent.offsetParent) {
      top += offsetParent.offsetTop;
    }
    return top;
  }

  /**
   * @return {boolean}
   */
  _targetIsVisible(top) {
    const dims = this._getWindowDims();
    return this.scrollMode === ScrollMode.KEEP_VISIBLE &&
        top > (dims.pageYOffset + this.scrollTopMargin) &&
        top < dims.pageYOffset + dims.innerHeight;
  }

  _calculateScrollToValue(top, target) {
    const dims = this._getWindowDims();
    return top + this.scrollTopMargin - (dims.innerHeight / 3) +
        (target.offsetHeight / 2);
  }

  _scrollToTarget() {
    if (!this.target || this.scrollMode === ScrollMode.NEVER) {
      return;
    }

    const dims = this._getWindowDims();
    const top = this._getTop(this.target);
    const bottomIsVisible = this._targetHeight ?
      this._targetIsVisible(top + this._targetHeight) : true;
    const scrollToValue = this._calculateScrollToValue(top, this.target);

    if (this._targetIsVisible(top)) {
      // Don't scroll if either the bottom is visible or if the position that
      // would get scrolled to is higher up than the current position. This
      // would cause less of the target content to be displayed than is
      // already.
      if (bottomIsVisible || scrollToValue < dims.scrollY) {
        return;
      }
    }

    // Scroll the element to the middle of the window. Dividing by a third
    // instead of half the inner height feels a bit better otherwise the
    // element appears to be below the center of the window even when it
    // isn't.
    window.scrollTo(dims.scrollX, scrollToValue);
  }

  _getWindowDims() {
    return {
      scrollX: window.scrollX,
      scrollY: window.scrollY,
      innerHeight: window.innerHeight,
      pageYOffset: window.pageYOffset,
    };
  }
}

customElements.define(GrCursorManager.is, GrCursorManager);
