/**
 * @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';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-cursor-manager_html';
import {ScrollMode} from '../../../constants/constants';
import {customElement, property, observe} from '@polymer/decorators';

export interface GrCursorManager {
  $: {};
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-cursor-manager': GrCursorManager;
  }
}

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

/**
 * Return type for cursor moves, that indicate whether a move was possible.
 */
export enum CursorMoveResult {
  /** The cursor was successfully moved. */
  MOVED,
  /** There were no stops - the cursor was reset. */
  NO_STOPS,
  /** There was no more stop to move to - the cursor was clipped to the end. */
  CLIPPED,
}

@customElement('gr-cursor-manager')
export class GrCursorManager extends GestureEventListeners(
  LegacyElementMixin(PolymerElement)
) {
  static get template() {
    return htmlTemplate;
  }

  @property({type: Object, notify: true})
  target: HTMLElement | null = null;

  /**
   * The height of content intended to be included with the target.
   */
  @property({type: Number})
  _targetHeight: number | null = null;

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

  /**
   * The class to apply to the current target. Use null for no class.
   */
  @property({type: String})
  cursorTargetClass: string | null = 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}
   */
  @property({type: String})
  scrollMode: string = ScrollMode.NEVER;

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

  private _lastDisplayedNavigateToNextFileToast: number | null = null;

  @property({type: Array})
  stops: HTMLElement[] = [];

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

  /**
   * Move the cursor forward. Clipped to the ends of the stop list.
   *
   * @param 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 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 clipToTop When none of the next indices match, move
   *     back to first instead of to last.
   * @param navigateToNextFile Navigate to next unreviewed file
   *     if user presses next on the last diff chunk
   * @return If a move was performed or why not.
   * @private
   */
  next(
    condition?: Function,
    getTargetHeight?: (target: HTMLElement) => number,
    clipToTop?: boolean,
    navigateToNextFile?: boolean
  ): CursorMoveResult {
    return this._moveCursor(
      1,
      condition,
      getTargetHeight,
      clipToTop,
      navigateToNextFile
    );
  }

  previous(condition?: Function): CursorMoveResult {
    return this._moveCursor(-1, 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 condition Optional condition. If a condition
   * is passed only stops which meet conditions are taken into account.
   */
  moveToVisibleArea(condition?: (el: Element) => boolean) {
    if (!this.stops || !this._isIntersectionObserverSupported()) {
      return;
    }
    const filteredStops = condition ? this.stops.filter(condition) : this.stops;
    const dims = this._getWindowDims();
    const windowCenter = Math.round(dims.innerHeight / 2);

    let closestToTheCenter: HTMLElement | null = null;
    let minDistanceToCenter: number | null = 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
        ) {
          // entry.target comes from the filteredStops array,
          // hence it is an HTMLElement
          closestToTheCenter = entry.target as HTMLElement;
          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 noScroll prevent any potential scrolling in response
   * setting the cursor.
   */
  setCursor(element: HTMLElement, noScroll?: boolean) {
    let behavior;
    if (noScroll) {
      behavior = this.scrollMode;
      this.scrollMode = ScrollMode.NEVER;
    }

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

    if (noScroll && behavior) {
      this.scrollMode = behavior;
    }
  }

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

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

  isAtEnd() {
    // Unset cursor should not be considered "at end", even when there are no
    // cursor stops.
    return this.index !== -1 && 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: number, noScroll?: boolean) {
    this.setCursor(this.stops[index], noScroll);
  }

  /**
   * Move the cursor forward or backward by delta. Clipped to the beginning or
   * end of stop list.
   *
   * @param delta either -1 or 1.
   * @param 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 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 clipToTop When none of the next indices match, move
   * back to first instead of to last.
   * @param navigateToNextFile Navigate to next unreviewed file
   * if user presses next on the last diff chunk
   * @return  If a move was performed or why not.
   * @private
   */
  _moveCursor(
    delta: number,
    condition?: Function,
    getTargetHeight?: (target: HTMLElement) => number,
    clipToTop?: boolean,
    navigateToNextFile?: boolean
  ): CursorMoveResult {
    if (!this.stops.length) {
      this.unsetCursor();
      return CursorMoveResult.NO_STOPS;
    }

    this._unDecorateTarget();

    const newIndex = this._getNextindex(delta, condition, clipToTop);
    const newTarget = newIndex !== -1 ? this.stops[newIndex] : null;

    const clipped = this.index === 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 (navigateToNextFile && clipped && this.isAtEnd()) {
      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 CursorMoveResult.CLIPPED;
      }
      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 CursorMoveResult.CLIPPED;
    }

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

    if (!newTarget) {
      return CursorMoveResult.NO_STOPS;
    }

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

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

    this._decorateTarget();

    return clipped ? CursorMoveResult.CLIPPED : CursorMoveResult.MOVED;
  }

  _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 delta either -1 or 1.
   * @param condition Optional stop condition.
   * @param clipToTop When none of the next indices match, move
   * back to first instead of to last.
   * @return the new index.
   * @private
   */
  _getNextindex(delta: number, condition?: Function, clipToTop?: boolean) {
    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) &&
      condition &&
      !condition(this.stops[newIndex])
    );

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

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

    return newIndex;
  }

  @observe('stops')
  _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 target Target to scroll to.
   * @return Distance to top of the target.
   */
  _getTop(target: HTMLElement) {
    let top: number = target.offsetTop;
    for (
      let offsetParent = target.offsetParent;
      offsetParent;
      offsetParent = (offsetParent as HTMLElement).offsetParent
    ) {
      top += (offsetParent as HTMLElement).offsetTop;
    }
    return top;
  }

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

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

  @observe('target')
  _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,
    };
  }
}
