/**
 * @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 {BehaviorSubject} from 'rxjs';
import {AbortStop, CursorMoveResult, Stop} from '../../../api/core';
import {ScrollMode} from '../../../constants/constants';

/**
 * Type guard and checker to check if a stop can be targeted.
 * Abort stops cannot be targeted.
 */
export function isTargetable(stop: Stop): stop is HTMLElement {
  return !(stop instanceof AbortStop);
}

export class GrCursorManager {
  get target(): HTMLElement | null {
    return this.targetSubject.getValue();
  }

  set target(target: HTMLElement | null) {
    this.targetSubject.next(target);
    this._scrollToTarget();
  }

  private targetSubject = new BehaviorSubject<HTMLElement | null>(null);

  target$ = this.targetSubject.asObservable();

  /**
   * The height of content intended to be included with the target.
   */
  _targetHeight: number | null = null;

  /**
   * The index of the current target (if any). -1 otherwise.
   */
  index = -1;

  /**
   * The class to apply to the current target. Use null for no class.
   */
  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}
   */
  scrollMode: string = ScrollMode.NEVER;

  /**
   * When true, will call element.focus() during scrolling.
   */
  focusOnMove = false;

  set stops(stops: Stop[]) {
    this.stopsInternal = stops;
    this._updateIndex();
  }

  get stops(): Stop[] {
    return this.stopsInternal;
  }

  private stopsInternal: Stop[] = [];

  /** Only non-AbortStop stops. */
  get targetableStops(): HTMLElement[] {
    return this.stops.filter(isTargetable);
  }

  /**
   * Move the cursor forward. Clipped to the end of the stop list.
   *
   * @param options.filter Skips any stops for which filter returns false.
   * @param options.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 options.clipToTop When none of the next indices match, move
   *     back to first instead of to last.
   * @param options.circular When on last element, you get to first element.
   * @return If a move was performed or why not.
   */
  next(
    options: {
      filter?: (stop: HTMLElement) => boolean;
      getTargetHeight?: (target: HTMLElement) => number;
      clipToTop?: boolean;
      circular?: boolean;
    } = {}
  ): CursorMoveResult {
    return this._moveCursor(1, options);
  }

  /**
   * Move the cursor backward. Clipped to the beginning of stop list.
   *
   * @param options.filter Skips any stops for which filter returns false.
   * @param options.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 options.clipToTop When none of the next indices match, move
   * back to first instead of to last.
   * @param options.circular When on first element, you get to last element.
   * @return  If a move was performed or why not.
   */
  previous(
    options: {
      filter?: (stop: HTMLElement) => boolean;
      circular?: boolean;
    } = {}
  ): CursorMoveResult {
    return this._moveCursor(-1, options);
  }

  /**
   * 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 filter Skips any stops for which filter returns false.
   */
  async moveToVisibleArea(filter?: (el: Element) => boolean) {
    const centerMostStop = await this.getCenterMostStop(filter);
    // 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.
    if (centerMostStop) {
      this.setCursor(centerMostStop, true);
    }
  }

  private async getCenterMostStop(
    filter?: (el: Element) => boolean
  ): Promise<HTMLElement | undefined> {
    const visibleEntries = await this.getVisibleEntries(filter);
    const windowCenter = Math.round(window.innerHeight / 2);

    let centerMostStop: HTMLElement | undefined = undefined;
    let minDistanceToCenter = Number.MAX_VALUE;

    for (const entry of visibleEntries) {
      // We are just using the entries here, because entry.boundingClientRect
      // is already computed, but entry.target.getBoundingClientRect() should
      // actually yield the same result.
      const center =
        entry.boundingClientRect.top +
        Math.round(entry.boundingClientRect.height / 2);
      const distanceToWindowCenter = Math.abs(center - windowCenter);
      if (distanceToWindowCenter < minDistanceToCenter) {
        // entry.target comes from the filteredStops array,
        // hence it is an HTMLElement
        centerMostStop = entry.target as HTMLElement;
        minDistanceToCenter = distanceToWindowCenter;
      }
    }
    return centerMostStop;
  }

  private async getVisibleEntries(
    filter?: (el: Element) => boolean
  ): Promise<IntersectionObserverEntry[]> {
    if (!this._isIntersectionObserverSupported()) {
      throw new Error('Intersection observing not supported');
    }
    if (!this.stops) {
      return [];
    }
    const filteredStops = filter
      ? this.targetableStops.filter(filter)
      : this.targetableStops;
    return new Promise(resolve => {
      let unobservedCount = filteredStops.length;
      const visibleEntries: IntersectionObserverEntry[] = [];
      const observer = new IntersectionObserver(entries => {
        visibleEntries.push(
          ...entries
            // In Edge it is recommended to use intersectionRatio instead of
            // isIntersecting.
            .filter(
              entry => entry.isIntersecting || entry.intersectionRatio > 0
            )
        );

        // 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.
        for (const entry of entries) {
          observer.unobserve(entry.target);
        }
        unobservedCount -= entries.length;
        if (unobservedCount === 0) {
          resolve(visibleEntries);
        }
      });
      for (const stop of filteredStops) {
        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 stop - if the given element is not one of
   * the stops, unset the cursor.
   *
   * @param noScroll prevent any potential scrolling in response
   * setting the cursor.
   */
  setCursor(element: HTMLElement, noScroll?: boolean) {
    if (!this.targetableStops.includes(element)) {
      this.unsetCursor();
      return;
    }
    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;
  }

  /** Returns true if there are no stops, or we are on the first stop. */
  isAtStart(): boolean {
    return this.stops.length === 0 || this.index === 0;
  }

  /** Returns true if there are no stops, or we are on the last stop. */
  isAtEnd(): boolean {
    return this.stops.length === 0 || this.index === this.stops.length - 1;
  }

  moveToStart() {
    if (this.stops.length) {
      this.setCursorAtIndex(0);
    }
  }

  moveToEnd() {
    if (this.stops.length) {
      this.setCursorAtIndex(this.stops.length - 1);
    }
  }

  setCursorAtIndex(index: number, noScroll?: boolean) {
    const stop = this.stops[index];
    if (isTargetable(stop)) {
      this.setCursor(stop, noScroll);
    }
  }

  _moveCursor(
    delta: number,
    {
      filter,
      getTargetHeight,
      clipToTop,
      circular,
    }: {
      filter?: (stop: HTMLElement) => boolean;
      getTargetHeight?: (target: HTMLElement) => number;
      clipToTop?: boolean;
      circular?: boolean;
    } = {}
  ): CursorMoveResult {
    if (!this.stops.length) {
      this.unsetCursor();
      return CursorMoveResult.NO_STOPS;
    }

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

    let clipped = false;
    let newStop: Stop;
    do {
      newIndex += delta;
      if (
        (delta > 0 && newIndex >= this.stops.length) ||
        (delta < 0 && newIndex < 0)
      ) {
        newIndex =
          (delta < 0 && !circular) || (delta > 0 && circular) || clipToTop
            ? 0
            : this.stops.length - 1;
        newStop = this.stops[newIndex];
        clipped = true;
        break;
      }
      // Sadly needed so that type narrowing understands that this.stops[newIndex] is
      // targetable after I have checked that.
      newStop = this.stops[newIndex];
    } while (isTargetable(newStop) && filter && !filter(newStop));

    if (!isTargetable(newStop)) {
      return CursorMoveResult.ABORTED;
    }

    this._unDecorateTarget();

    this.index = newIndex;
    this.target = newStop;

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

    if (this.focusOnMove) {
      this.target.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);
    }
  }

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

    const newIndex = this.stops.indexOf(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;
  }

  _targetIsVisible(top: number) {
    return (
      this.scrollMode === ScrollMode.KEEP_VISIBLE &&
      top > window.pageYOffset &&
      top < window.pageYOffset + window.innerHeight
    );
  }

  _calculateScrollToValue(top: number, target: HTMLElement) {
    return top + -window.innerHeight / 3 + target.offsetHeight / 2;
  }

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

    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 < window.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(window.scrollX, scrollToValue);
  }
}
