/**
 * @license
 * Copyright (C) 2020 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 '../../../styles/shared-styles';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom';
import {Debouncer} from '@polymer/polymer/lib/utils/debounce';
import {timeOut} from '@polymer/polymer/lib/utils/async';
import {getRootElement} from '../../../scripts/rootElement';
import {Constructor} from '../../../utils/common-util';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {dedupingMixin} from '@polymer/polymer/lib/utils/mixin';
import {property, observe} from '@polymer/decorators';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
import {
  pushScrollLock,
  removeScrollLock,
} from '@polymer/iron-overlay-behavior/iron-scroll-manager';

const HOVER_CLASS = 'hovered';
const HIDE_CLASS = 'hide';

/**
 * How long should we wait before showing the hovercard when the user hovers
 * over the element?
 */
const SHOW_DELAY_MS = 550;

/**
 * How long should we wait before hiding the hovercard when the user moves from
 * target to the hovercard.
 *
 * Note: this should be lower than SHOW_DELAY_MS to avoid flickering.
 */
const HIDE_DELAY_MS = 500;

/**
 * The mixin for gr-hovercard-behavior.
 *
 * @example
 *
 * // LegacyElementMixin is still needed to support the old lifecycles
 * // TODO: Replace old life cycles with new ones.
 *
 * class YourComponent extends hovercardBehaviorMixin(
 *  LegacyElementMixin(PolymerElement)
 *
 * @see gr-hovercard.ts
 *
 * // following annotations are required for polylint
 * @polymer
 * @mixinFunction
 */
export const hovercardBehaviorMixin = dedupingMixin(
  <T extends Constructor<PolymerElement & LegacyElementMixin>>(
    superClass: T
  ): T & Constructor<GrHovercardBehaviorInterface> => {
    /**
     * @polymer
     * @mixinClass
     */
    class Mixin extends superClass {
      @property({type: Object})
      _target: Element | null = null;

      // Determines whether or not the hovercard is visible.
      @property({type: Boolean})
      _isShowing = false;

      // The `id` of the element that the hovercard is anchored to.
      @property({type: String})
      for?: string;

      /**
       * The spacing between the top of the hovercard and the element it is
       * anchored to.
       */
      @property({type: Number})
      offset = 14;

      /**
       * Positions the hovercard to the top, right, bottom, left, bottom-left,
       * bottom-right, top-left, or top-right of its content.
       */
      @property({type: String})
      position = 'right';

      @property({type: Object})
      container: HTMLElement | null = null;

      /**
       * ID for the container element.
       */
      @property({type: String})
      containerId = 'gr-hovercard-container';

      private _hideDebouncer: Debouncer | null = null;

      private _showDebouncer: Debouncer | null = null;

      private _isScheduledToShow?: boolean;

      private _isScheduledToHide?: boolean;

      /** @override */
      attached() {
        super.attached();
        if (!this._target) {
          this._target = this.target;
        }
        this.listen(this._target, 'mouseenter', 'debounceShow');
        this.listen(this._target, 'focus', 'debounceShow');
        this.listen(this._target, 'mouseleave', 'debounceHide');
        this.listen(this._target, 'blur', 'debounceHide');

        // when click, dismiss immediately
        this.listen(this._target, 'click', 'hide');

        // show the hovercard if mouse moves to hovercard
        // this will cancel pending hide as well
        this.listen(this, 'mouseenter', 'show');
        this.listen(this, 'mouseenter', 'lock');
        // when leave hovercard, hide it immediately
        this.listen(this, 'mouseleave', 'hide');
        this.listen(this, 'mouseleave', 'unlock');
      }

      detached() {
        super.detached();
        this.unlock();
      }

      /** @override */
      ready() {
        super.ready();
        // First, check to see if the container has already been created.
        this.container = getRootElement().querySelector('#' + this.containerId);

        if (this.container) {
          return;
        }

        // If it does not exist, create and initialize the hovercard container.
        this.container = document.createElement('div');
        this.container.setAttribute('id', this.containerId);
        getRootElement().appendChild(this.container);
      }

      removeListeners() {
        this.unlisten(this._target, 'mouseenter', 'debounceShow');
        this.unlisten(this._target, 'focus', 'debounceShow');
        this.unlisten(this._target, 'mouseleave', 'debounceHide');
        this.unlisten(this._target, 'blur', 'debounceHide');
        this.unlisten(this._target, 'click', 'hide');
      }

      debounceHide() {
        this.cancelShowDebouncer();
        if (!this._isShowing || this._isScheduledToHide) return;
        this._isScheduledToHide = true;
        this._hideDebouncer = Debouncer.debounce(
          this._hideDebouncer,
          timeOut.after(HIDE_DELAY_MS),
          () => {
            // This happens when hide immediately through click or mouse leave
            // on the hovercard
            if (!this._isScheduledToHide) return;
            this.hide();
          }
        );
      }

      cancelHideDebouncer() {
        if (this._hideDebouncer) {
          this._hideDebouncer.cancel();
          this._isScheduledToHide = false;
        }
      }

      /**
       * Hovercard elements are created outside of <gr-app>, so if you want to fire
       * events, then you probably want to do that through the target element.
       */
      dispatchEventThroughTarget(eventName: string, detail?: unknown) {
        if (!detail) detail = {};
        if (this._target)
          this._target.dispatchEvent(
            new CustomEvent(eventName, {
              detail,
              bubbles: true,
              composed: true,
            })
          );
      }

      /**
       * Returns the target element that the hovercard is anchored to (the `id` of
       * the `for` property).
       */
      get target(): Element {
        const parentNode = this.parentNode;
        // If the parentNode is a document fragment, then we need to use the host.
        const ownerRoot = this.getRootNode() as ShadowRoot;
        let target;
        if (this.for) {
          target = ownerRoot.querySelector('#' + this.for);
        } else {
          target =
            !parentNode || parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE
              ? ownerRoot.host
              : parentNode;
        }
        return target as Element;
      }

      /**
       * unlock scroll, this will resume the scroll outside of the hovercard.
       */
      unlock() {
        removeScrollLock(this);
      }

      /**
       * Hides/closes the hovercard. This occurs when the user triggers the
       * `mouseleave` event on the hovercard's `target` element (as long as the
       * user is not hovering over the hovercard).
       *
       */
      hide(e?: MouseEvent) {
        this.cancelHideDebouncer();
        this.cancelShowDebouncer();
        if (!this._isShowing) {
          return;
        }

        // If the user is now hovering over the hovercard or the user is returning
        // from the hovercard but now hovering over the target (to stop an annoying
        // flicker effect), just return.
        if (e) {
          if (
            e.relatedTarget === this ||
            (e.target === this && e.relatedTarget === this._target)
          ) {
            return;
          }
        }

        // Mark that the hovercard is not visible and do not allow focusing
        this._isShowing = false;

        // Clear styles in preparation for the next time we need to show the card
        this.classList.remove(HOVER_CLASS);

        // Reset and remove the hovercard from the DOM
        this.style.cssText = '';
        this.$['container'].setAttribute('tabindex', '-1');

        // Remove the hovercard from the container, given that it is still a child
        // of the container.
        if (this.container?.contains(this)) {
          this.container.removeChild(this);
        }
      }

      /**
       * Shows/opens the hovercard with a fixed delay.
       */
      debounceShow() {
        this.debounceShowBy(SHOW_DELAY_MS);
      }

      /**
       * Shows/opens the hovercard with the given delay.
       */
      debounceShowBy(delayMs: number) {
        this.cancelHideDebouncer();
        if (this._isShowing || this._isScheduledToShow) return;
        this._isScheduledToShow = true;
        this._showDebouncer = Debouncer.debounce(
          this._showDebouncer,
          timeOut.after(delayMs),
          () => {
            // This happens when the mouse leaves the target before the delay is over.
            if (!this._isScheduledToShow) return;
            this.show();
          }
        );
      }

      cancelShowDebouncer() {
        if (this._showDebouncer) {
          this._showDebouncer.cancel();
          this._isScheduledToShow = false;
        }
      }

      /**
       * Lock background scroll but enable scroll inside of current hovercard.
       */
      lock() {
        pushScrollLock(this);
      }

      /**
       * Shows/opens the hovercard. This occurs when the user triggers the
       * `mousenter` event on the hovercard's `target` element.
       */
      show() {
        this.cancelHideDebouncer();
        this.cancelShowDebouncer();
        if (this._isShowing || !this.container) {
          return;
        }

        // Mark that the hovercard is now visible
        this._isShowing = true;
        this.setAttribute('tabindex', '0');

        // Add it to the DOM and calculate its position
        this.container.appendChild(this);
        // We temporarily hide the hovercard until we have found the correct
        // position for it.
        this.classList.add(HIDE_CLASS);
        this.classList.add(HOVER_CLASS);
        // Make sure that the hovercard actually rendered and all dom-if
        // statements processed, so that we can measure the (invisible)
        // hovercard properly in updatePosition().
        flush();
        this.updatePosition();
        this.classList.remove(HIDE_CLASS);
      }

      updatePosition() {
        const positionsToTry = new Set([
          this.position,
          'right',
          'bottom-right',
          'top-right',
          'bottom',
          'top',
          'bottom-left',
          'top-left',
          'left',
        ]);
        for (const position of positionsToTry) {
          this.updatePositionTo(position);
          if (this._isInsideViewport()) return;
        }
        console.warn('Could not find a visible position for the hovercard.');
      }

      _isInsideViewport() {
        const thisRect = this.getBoundingClientRect();
        if (thisRect.top < 0) return false;
        if (thisRect.left < 0) return false;
        const docuRect = document.documentElement.getBoundingClientRect();
        if (thisRect.bottom > docuRect.height) return false;
        if (thisRect.right > docuRect.width) return false;
        return true;
      }

      /**
       * Updates the hovercard's position based the current position of the `target`
       * element.
       *
       * The hovercard is supposed to stay open if the user hovers over it.
       * To keep it open when the user moves away from the target, the bounding
       * rects of the target and hovercard must touch or overlap.
       *
       * NOTE: You do not need to directly call this method unless you need to
       * update the position of the tooltip while it is already visible (the
       * target element has moved and the tooltip is still open).
       */
      updatePositionTo(position: string) {
        if (!this._target) {
          return;
        }

        // Make sure that thisRect will not get any paddings and such included
        // in the width and height of the bounding client rect.
        this.style.cssText = '';

        const docuRect = document.documentElement.getBoundingClientRect();
        const targetRect = this._target.getBoundingClientRect();
        const thisRect = this.getBoundingClientRect();

        const targetLeft = targetRect.left - docuRect.left;
        const targetTop = targetRect.top - docuRect.top;

        let hovercardLeft;
        let hovercardTop;

        switch (position) {
          case 'top':
            hovercardLeft =
              targetLeft + (targetRect.width - thisRect.width) / 2;
            hovercardTop = targetTop - thisRect.height - this.offset;
            break;
          case 'bottom':
            hovercardLeft =
              targetLeft + (targetRect.width - thisRect.width) / 2;
            hovercardTop = targetTop + targetRect.height + this.offset;
            break;
          case 'left':
            hovercardLeft = targetLeft - thisRect.width - this.offset;
            hovercardTop =
              targetTop + (targetRect.height - thisRect.height) / 2;
            break;
          case 'right':
            hovercardLeft = targetLeft + targetRect.width + this.offset;
            hovercardTop =
              targetTop + (targetRect.height - thisRect.height) / 2;
            break;
          case 'bottom-right':
            hovercardLeft = targetLeft + targetRect.width + this.offset;
            hovercardTop = targetTop;
            break;
          case 'bottom-left':
            hovercardLeft = targetLeft - thisRect.width - this.offset;
            hovercardTop = targetTop;
            break;
          case 'top-left':
            hovercardLeft = targetLeft - thisRect.width - this.offset;
            hovercardTop = targetTop + targetRect.height - thisRect.height;
            break;
          case 'top-right':
            hovercardLeft = targetLeft + targetRect.width + this.offset;
            hovercardTop = targetTop + targetRect.height - thisRect.height;
            break;
        }

        this.style.left = `${hovercardLeft}px`;
        this.style.top = `${hovercardTop}px`;
      }

      /**
       * Responds to a change in the `for` value and gets the updated `target`
       * element for the hovercard.
       */
      @observe('for')
      _forChanged() {
        this._target = this.target;
      }
    }

    return Mixin;
  }
);

export interface GrHovercardBehaviorInterface {
  attached(): void;
  ready(): void;
  removeListeners(): void;
  debounceHide(): void;
  cancelHideDebouncer(): void;
  dispatchEventThroughTarget(eventName: string, detail?: unknown): void;
  hide(e?: MouseEvent): void;
  debounceShow(): void;
  debounceShowBy(delayMs: number): void;
  cancelShowDebouncer(): void;
  show(): void;
  updatePosition(): void;
  updatePositionTo(position: string): void;
}
