/**
 * @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 '../../elements/shared/gr-tooltip/gr-tooltip';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom';
import {getRootElement} from '../../scripts/rootElement';
import {property, observe} from '@polymer/decorators';
import {dedupingMixin} from '@polymer/polymer/lib/utils/mixin';
import {GrTooltip} from '../../elements/shared/gr-tooltip/gr-tooltip';
import {PolymerElement} from '@polymer/polymer';
import {Constructor} from '../../utils/common-util';

const BOTTOM_OFFSET = 7.2; // Height of the arrow in tooltip.

/** The interface corresponding to TooltipMixin */
export interface TooltipMixinInterface {
  hasTooltip: boolean;
  positionBelow: boolean;
  _isTouchDevice: boolean;
  _tooltip: GrTooltip | null;
  _titleText: string;
  _hasSetupTooltipListeners: boolean;
}

/**
 * @polymer
 * @mixinFunction
 */
export const TooltipMixin = dedupingMixin(
  <T extends Constructor<PolymerElement>>(
    superClass: T
  ): T & Constructor<TooltipMixinInterface> => {
    /**
     * @polymer
     * @mixinClass
     */
    class Mixin extends superClass {
      @property({type: Boolean})
      hasTooltip = false;

      @property({type: Boolean, reflectToAttribute: true})
      positionBelow = false;

      @property({type: Boolean})
      _isTouchDevice = 'ontouchstart' in document.documentElement;

      @property({type: Object})
      _tooltip: GrTooltip | null = null;

      @property({type: String})
      _titleText = '';

      @property({type: Boolean})
      _hasSetupTooltipListeners = false;

      // Handler for mouseenter event
      private mouseenterHandler?: (e: MouseEvent) => void;

      // Handler for scrolling on window
      private readonly windowScrollHandler: () => void;

      // Handler for showing the tooltip, will be attached to certain events
      private readonly showHandler: () => void;

      // Handler for hiding the tooltip, will be attached to certain events
      private readonly hideHandler: (e: Event) => void;

      // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
      constructor(..._: any[]) {
        super();
        this.windowScrollHandler = () => this._handleWindowScroll();
        this.showHandler = () => this._handleShowTooltip();
        this.hideHandler = (e: Event | undefined) => this._handleHideTooltip(e);
      }

      /** @override */
      disconnectedCallback() {
        // NOTE: if you define your own `detached` in your component
        // then this won't take affect (as its not a class yet)
        this._handleHideTooltip(undefined);
        if (this.mouseenterHandler) {
          this.removeEventListener('mouseenter', this.mouseenterHandler);
        }
        window.removeEventListener('scroll', this.windowScrollHandler);
        super.disconnectedCallback();
      }

      @observe('hasTooltip')
      _setupTooltipListeners() {
        if (!this.mouseenterHandler) {
          this.mouseenterHandler = this.showHandler;
        }

        if (!this.hasTooltip) {
          // if attribute set to false, remove the listener
          this.removeEventListener('mouseenter', this.mouseenterHandler);
          this._hasSetupTooltipListeners = false;
          return;
        }

        if (this._hasSetupTooltipListeners) {
          return;
        }
        this._hasSetupTooltipListeners = true;

        this.addEventListener('mouseenter', this.mouseenterHandler);
      }

      _handleShowTooltip() {
        if (this._isTouchDevice) {
          return;
        }

        if (
          !this.hasAttribute('title') ||
          this.getAttribute('title') === '' ||
          this._tooltip
        ) {
          return;
        }

        // Store the title attribute text then set it to an empty string to
        // prevent it from showing natively.
        this._titleText = this.getAttribute('title') || '';
        this.setAttribute('title', '');

        const tooltip = document.createElement('gr-tooltip');
        tooltip.text = this._titleText;
        tooltip.maxWidth = this.getAttribute('max-width') || '';
        tooltip.positionBelow = this.hasAttribute('position-below');

        // Set visibility to hidden before appending to the DOM so that
        // calculations can be made based on the element’s size.
        tooltip.style.visibility = 'hidden';
        getRootElement().appendChild(tooltip);
        this._positionTooltip(tooltip);
        tooltip.style.visibility = 'initial';

        this._tooltip = tooltip;
        window.addEventListener('scroll', this.windowScrollHandler);
        this.addEventListener('mouseleave', this.hideHandler);
        this.addEventListener('click', this.hideHandler);
        tooltip.addEventListener('mouseleave', this.hideHandler);
      }

      _handleHideTooltip(e: Event | undefined) {
        if (this._isTouchDevice) {
          return;
        }
        if (!this.hasAttribute('title') || !this._titleText) {
          return;
        }
        // Do not hide if mouse left this or this._tooltip and came to this or
        // this._tooltip
        if (
          (e as MouseEvent)?.relatedTarget === this._tooltip ||
          (e as MouseEvent)?.relatedTarget === this
        ) {
          return;
        }

        window.removeEventListener('scroll', this.windowScrollHandler);
        this.removeEventListener('mouseleave', this.hideHandler);
        this.removeEventListener('click', this.hideHandler);
        this.setAttribute('title', this._titleText);
        this._tooltip?.removeEventListener('mouseleave', this.hideHandler);

        if (this._tooltip?.parentNode) {
          this._tooltip.parentNode.removeChild(this._tooltip);
        }
        this._tooltip = null;
      }

      _handleWindowScroll() {
        if (!this._tooltip) {
          return;
        }

        this._positionTooltip(this._tooltip);
      }

      _positionTooltip(tooltip: GrTooltip) {
        // This flush is needed for tooltips to be positioned correctly in Firefox
        // and Safari.
        flush();
        const rect = this.getBoundingClientRect();
        const boxRect = tooltip.getBoundingClientRect();
        if (!tooltip.parentElement) {
          return;
        }
        const parentRect = tooltip.parentElement.getBoundingClientRect();
        const top = rect.top - parentRect.top;
        const left =
          rect.left - parentRect.left + (rect.width - boxRect.width) / 2;
        const right = parentRect.width - left - boxRect.width;
        if (left < 0) {
          tooltip.updateStyles({
            '--gr-tooltip-arrow-center-offset': `${left}px`,
          });
        } else if (right < 0) {
          tooltip.updateStyles({
            '--gr-tooltip-arrow-center-offset': `${-0.5 * right}px`,
          });
        }
        tooltip.style.left = `${Math.max(0, left)}px`;

        if (!this.positionBelow) {
          tooltip.style.top = `${Math.max(0, top)}px`;
          tooltip.style.transform = `translateY(calc(-100% - ${BOTTOM_OFFSET}px))`;
        } else {
          tooltip.style.top = `${top + rect.height + BOTTOM_OFFSET}px`;
        }
      }
    }

    return Mixin;
  }
);
