/**
 * @license
 * Scale https://github.com/telekom/scale
 *
 * Copyright (c) 2021 Egor Kirpichev and contributors, Deutsche Telekom AG
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */
import { Component, Element, Event, Host, Method, Prop, Watch, h, State, } from '@stencil/core';
import Popover from './utilities/popover';
let id = 0;
export class Tooltip {
  constructor() {
    this.componentId = `tooltip-${++id}`;
    this.isVisible = false;
    /** (optional) The content of the Tooltip supporting Text only */
    this.content = '';
    /** (optional) Position of the Tooltip on the Object */
    this.placement = 'top';
    /** (optional) Disable Tooltip */
    this.disabled = false;
    /** (optional) Distance of the Tooltip from the Target Object (related to the `placement`) */
    this.distance = 5;
    /** (optional) Set the Tooltip to open per default (will still be closed on closing Events) */
    this.open = false;
    /** (optional) skidding moves the tooltip of the element in dependence of its `placement` to the element either
     * on an x-axis (at `placement` top/down) or on a y-axis (for output `placement` left/right)
     */
    this.skidding = 0;
    /** (optional) Set custom trigger Event selection */
    this.trigger = 'hover focus';
    /** (optional) Switching the flip option of the tooltip on and off */
    this.flip = true;
    /** (optional) Switching the preventOverflow option of the tooltip on and off */
    this.preventOverflow = false;
    this.mouseOverTooltip = false;
  }
  handleOpenChange() {
    this.open ? this.showTooltip() : this.hideTooltip();
  }
  connectedCallback() {
    this.handleBlur = this.handleBlur.bind(this);
    this.handleClick = this.handleClick.bind(this);
    this.handleFocus = this.handleFocus.bind(this);
    this.handleKeyDown = this.handleKeyDown.bind(this);
    this.handleMouseOver = this.handleMouseOver.bind(this);
    this.handleMouseOut = this.handleMouseOut.bind(this);
    this.handleSlotChange = this.handleSlotChange.bind(this);
  }
  componentDidLoad() {
    this.target = this.getTarget();
    this.popover = new Popover(this.target, this.tooltipPositioner);
    this.syncPopoverOptions();
    this.host.addEventListener('blur', this.handleBlur, true);
    this.host.addEventListener('click', this.handleClick, true);
    this.host.addEventListener('focus', this.handleFocus, true);
    this.tooltipPositioner.hidden = !this.open;
    if (this.open) {
      this.showTooltip();
    }
  }
  componentDidUpdate() {
    this.syncPopoverOptions();
  }
  disconnectedCallback() {
    this.popover.destroy();
    this.host.removeEventListener('blur', this.handleBlur, true);
    this.host.removeEventListener('click', this.handleClick, true);
    this.host.removeEventListener('focus', this.handleFocus, true);
  }
  async showTooltip() {
    if (this.isVisible) {
      return;
    }
    const scaleShow = this.tooltipBeforeShow.emit();
    if (scaleShow.defaultPrevented) {
      this.open = false;
      return;
    }
    this.isVisible = true;
    this.open = true;
    this.popover.show();
  }
  async hideTooltip() {
    if (!this.isVisible) {
      return;
    }
    const tooltipBeforeHide = this.tooltipBeforeHide.emit();
    if (tooltipBeforeHide.defaultPrevented) {
      this.open = true;
      return;
    }
    this.isVisible = false;
    this.open = false;
    this.popover.hide();
  }
  getTarget() {
    const target = this.host.shadowRoot.querySelector('.slot-container');
    if (!target) {
      throw new Error('Invalid tooltip target: no child element was found.');
    }
    return target;
  }
  handleBlur() {
    if (this.hasTrigger('focus')) {
      this.hideTooltip();
    }
  }
  handleClick() {
    if (this.hasTrigger('click')) {
      this.open ? this.hideTooltip() : this.showTooltip();
    }
  }
  handleFocus() {
    if (this.hasTrigger('focus')) {
      this.showTooltip();
    }
  }
  handleKeyDown(event) {
    if (this.open && event.key === 'Escape') {
      event.stopPropagation();
      this.hideTooltip();
    }
  }
  handleMouseOver() {
    if (this.hasTrigger('hover')) {
      this.showTooltip();
    }
  }
  handleTooltipMouseOver() {
    this.mouseOverTooltip = true;
  }
  handleMouseOut() {
    if (!this.mouseOverTooltip) {
      if (this.hasTrigger('hover')) {
        this.hideTooltip();
      }
    }
  }
  handleSlotChange() {
    const oldTarget = this.target;
    const newTarget = this.getTarget();
    if (newTarget !== oldTarget) {
      if (oldTarget) {
        oldTarget.removeAttribute('aria-describedby');
      }
      newTarget.setAttribute('aria-describedby', this.componentId);
    }
  }
  hasTrigger(triggerType) {
    const triggers = this.trigger.split(' ');
    return triggers.includes(triggerType);
  }
  syncPopoverOptions() {
    this.popover.setOptions({
      placement: this.placement,
      distance: this.distance,
      skidding: this.skidding,
      transitionElement: this.tooltip,
      onAfterHide: () => this.tooltipHide.emit(),
      onAfterShow: () => this.tooltipShow.emit(),
    });
    this.popover.setPreventOverflow(this.preventOverflow);
    this.popover.setFlip(this.flip);
  }
  render() {
    return (h(Host, { class: "host-container", onKeyDown: this.handleKeyDown, onMouseOver: this.handleMouseOver, onMouseOut: this.handleMouseOut },
      this.styles && h("style", null, this.styles),
      h("div", { class: "slot-container" },
        h("slot", { onSlotchange: this.handleSlotChange })),
      !this.disabled && (h("div", { class: "tooltip-positioner", ref: (el) => (this.tooltipPositioner = el), onMouseOver: this.handleTooltipMouseOver },
        h("div", { class: {
            tooltip: true,
            'tooltip--open': this.open,
          }, onMouseOver: this.handleTooltipMouseOver, part: "base", ref: (el) => (this.tooltip = el), id: this.componentId, role: "tooltip", "aria-hidden": this.open ? 'false' : 'true' },
          h("div", { class: "content-wrapper", tabindex: 0 },
            h("slot", { name: "content" }, this.content)))))));
  }
  static get is() { return "scale-tooltip"; }
  static get encapsulation() { return "shadow"; }
  static get originalStyleUrls() { return {
    "$": ["tooltip.css"]
  }; }
  static get styleUrls() { return {
    "$": ["tooltip.css"]
  }; }
  static get properties() { return {
    "content": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "(optional) The content of the Tooltip supporting Text only"
      },
      "attribute": "content",
      "reflect": false,
      "defaultValue": "''"
    },
    "placement": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "| 'top'\n    | 'top-start'\n    | 'top-end'\n    | 'right'\n    | 'right-start'\n    | 'right-end'\n    | 'bottom'\n    | 'bottom-start'\n    | 'bottom-end'\n    | 'left'\n    | 'left-start'\n    | 'left-end'",
        "resolved": "\"bottom\" | \"bottom-end\" | \"bottom-start\" | \"left\" | \"left-end\" | \"left-start\" | \"right\" | \"right-end\" | \"right-start\" | \"top\" | \"top-end\" | \"top-start\"",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "(optional) Position of the Tooltip on the Object"
      },
      "attribute": "placement",
      "reflect": false,
      "defaultValue": "'top'"
    },
    "disabled": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "(optional) Disable Tooltip"
      },
      "attribute": "disabled",
      "reflect": false,
      "defaultValue": "false"
    },
    "distance": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "(optional) Distance of the Tooltip from the Target Object (related to the `placement`)"
      },
      "attribute": "distance",
      "reflect": false,
      "defaultValue": "5"
    },
    "open": {
      "type": "boolean",
      "mutable": true,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "(optional) Set the Tooltip to open per default (will still be closed on closing Events)"
      },
      "attribute": "open",
      "reflect": true,
      "defaultValue": "false"
    },
    "skidding": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "(optional) skidding moves the tooltip of the element in dependence of its `placement` to the element either\non an x-axis (at `placement` top/down) or on a y-axis (for output `placement` left/right)"
      },
      "attribute": "skidding",
      "reflect": false,
      "defaultValue": "0"
    },
    "trigger": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "(optional) Set custom trigger Event selection"
      },
      "attribute": "trigger",
      "reflect": false,
      "defaultValue": "'hover focus'"
    },
    "flip": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "(optional) Switching the flip option of the tooltip on and off"
      },
      "attribute": "flip",
      "reflect": false,
      "defaultValue": "true"
    },
    "preventOverflow": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "(optional) Switching the preventOverflow option of the tooltip on and off"
      },
      "attribute": "prevent-overflow",
      "reflect": false,
      "defaultValue": "false"
    },
    "styles": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) Injected CSS styles"
      },
      "attribute": "styles",
      "reflect": false
    }
  }; }
  static get states() { return {
    "mouseOverTooltip": {}
  }; }
  static get events() { return [{
      "method": "tooltipBeforeShow",
      "name": "scale-before-show",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "any",
        "resolved": "any",
        "references": {}
      }
    }, {
      "method": "tooltipShow",
      "name": "scale-show",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "any",
        "resolved": "any",
        "references": {}
      }
    }, {
      "method": "tooltipBeforeHide",
      "name": "scale-before-hide",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "any",
        "resolved": "any",
        "references": {}
      }
    }, {
      "method": "tooltipHide",
      "name": "scale-hide",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "any",
        "resolved": "any",
        "references": {}
      }
    }]; }
  static get methods() { return {
    "showTooltip": {
      "complexType": {
        "signature": "() => Promise<void>",
        "parameters": [],
        "references": {
          "Promise": {
            "location": "global"
          }
        },
        "return": "Promise<void>"
      },
      "docs": {
        "text": "",
        "tags": []
      }
    },
    "hideTooltip": {
      "complexType": {
        "signature": "() => Promise<void>",
        "parameters": [],
        "references": {
          "Promise": {
            "location": "global"
          }
        },
        "return": "Promise<void>"
      },
      "docs": {
        "text": "",
        "tags": []
      }
    }
  }; }
  static get elementRef() { return "host"; }
  static get watchers() { return [{
      "propName": "open",
      "methodName": "handleOpenChange"
    }]; }
}
