/**
 * @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.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {getRootElement} from '../../../scripts/rootElement.js';

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

/**
 * When the hovercard is positioned diagonally (bottom-left, bottom-right,
 * top-left, or top-right), we add additional (invisible) padding so that the
 * area that a user can hover over to access the hovercard is larger.
 */
const DIAGONAL_OVERFLOW = 15;

/**
 * How long should be wait before showing the hovercard when the user hovers
 * over the element?
 */
const SHOW_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)
 * ) {
 *   static get is() { return ''; }
 *   static get template() { return html``; }
 * }
 *
 * customElements.define(GrHovercard.is, GrHovercard);
 *
 * @see gr-hovercard.js
 *
 * // following annotations are required for polylint
 * @polymer
 * @mixinFunction
 */
export const hovercardBehaviorMixin = superClass => class extends superClass {
  static get properties() {
    return {
      /**
       * @type {?}
       */
      _target: Object,

      /**
       * Determines whether or not the hovercard is visible.
       *
       * @type {boolean}
       */
      _isShowing: {
        type: Boolean,
        value: false,
      },
      /**
       * The `id` of the element that the hovercard is anchored to.
       *
       * @type {string}
       */
      for: {
        type: String,
        observer: '_forChanged',
      },

      /**
       * The spacing between the top of the hovercard and the element it is
       * anchored to.
       *
       * @type {number}
       */
      offset: {
        type: Number,
        value: 14,
      },

      /**
       * Positions the hovercard to the top, right, bottom, left, bottom-left,
       * bottom-right, top-left, or top-right of its content.
       *
       * @type {string}
       */
      position: {
        type: String,
        value: 'right',
      },

      container: Object,
      /**
       * ID for the container element.
       *
       * @type {string}
       */
      containerId: {
        type: String,
        value: 'gr-hovercard-container',
      },
    };
  }

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

  /** @override */
  created() {
    super.created();
    this.addEventListener('mouseleave',
        e => this.hide(e));
  }

  /** @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', 'show');
    this.unlisten(this._target, 'focus', 'show');
    this.unlisten(this._target, 'mouseleave', 'hide');
    this.unlisten(this._target, 'blur', 'hide');
    this.unlisten(this._target, 'click', 'hide');
  }

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

  /**
   * 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).
   *
   * @param {Event} opt_e DOM Event (e.g. `mouseleave` event)
   */
  hide(opt_e) {
    this._isScheduledToShow = false;
    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 (opt_e) {
      if (opt_e.toElement === this ||
          (opt_e.fromElement === this && opt_e.toElement === 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.
   */
  showDelayed() {
    this.showDelayedBy(SHOW_DELAY_MS);
  }

  /**
   * Shows/opens the hovercard with the given delay.
   */
  showDelayedBy(delayMs) {
    if (this._isShowing || this._isScheduledToShow) return;
    this._isScheduledToShow = true;
    setTimeout(() => {
      // This happens when the mouse leaves the target before the delay is over.
      if (!this._isScheduledToShow) return;
      this._isScheduledToShow = false;
      this.show();
    }, delayMs);
  }

  /**
   * Shows/opens the hovercard. This occurs when the user triggers the
   * `mousenter` event on the hovercard's `target` element.
   */
  show() {
    if (this._isShowing) {
      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);
    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) {
    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;
    const diagonalPadding = this.offset + DIAGONAL_OVERFLOW;
    let cssText = '';

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

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

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