var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
    r = Reflect.decorate(decorators, target, key, desc);
  else
    for (var i = decorators.length - 1; i >= 0; i--)
      if (d = decorators[i])
        r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { h, Host, } from "@stencil/core";
import { Logger } from "../../utils/log";
import { BEM } from "../../utils/bem";
import { balBrowser } from "../../utils/browser";
import { balDevice } from "../../utils/device";
import { showContainerElement, showArrowElement, hideContainerElement, hideArrowElement } from "./bal-tooltip.util";
import { computePosition, offset, arrow, flip, autoUpdate, shift } from "@floating-ui/dom";
export class Tooltip {
  constructor() {
    this.tooltipId = `bal-to-${tooltipIds++}`;
    this.reference = '';
    this.placement = 'bottom';
    this.offset = 0;
    this.demo = false;
    this.presented = false;
    this.contentWidth = undefined;
  }
  createLogger(log) {
    this.log = log;
  }
  contentWidthChanged(newValue, oldValue) {
    if (newValue !== oldValue) {
      if (newValue === undefined) {
        this.el.style.removeProperty('--bal-tooltip-max-width');
      }
      else {
        this.el.style.setProperty('--bal-tooltip-max-width', `${this.contentWidth}px`);
      }
    }
  }
  componentDidLoad() {
    this.contentWidthChanged(this.contentWidth, 0);
    if (!balDevice.hasTouchScreen) {
      let showEvents = [];
      let hideEvents = [];
      showEvents = ['mouseenter', 'focus'];
      hideEvents = ['mouseleave', 'blur'];
      showEvents.forEach(event => {
        if (this.triggerElement) {
          this.triggerElement.addEventListener(event, () => this.present());
        }
      });
      hideEvents.forEach(event => {
        if (this.triggerElement) {
          this.triggerElement.addEventListener(event, () => this.dismiss());
        }
      });
    }
    if (this.demo) {
      this.present();
    }
  }
  async present() {
    if (!this.trigger && balBrowser.hasDocument) {
      const firstTrigger = Array.from(document.querySelectorAll(`[id="${this.reference}"]`))[0];
      this.trigger = firstTrigger;
    }
    if (this.trigger && this.containerEl && this.arrowEl) {
      this.balWillAnimate.emit();
      const triggerVariantAttr = this.trigger.attributes.getNamedItem('bal-tooltip-placement');
      if (triggerVariantAttr) {
        this.placement = triggerVariantAttr.value;
      }
      else {
        this.placement = this.placement;
      }
      showContainerElement(this.containerEl);
      showArrowElement(this.arrowEl);
      this.trigger.classList.add('bal-tooltip-trigger');
      this.presented = true;
      this.cleanup = autoUpdate(this.trigger, this.containerEl, () => {
        this.update();
      }, {
        ancestorScroll: true,
        ancestorResize: true,
        elementResize: false,
        layoutShift: true,
        animationFrame: true,
      });
      this.balDidAnimate.emit();
      return true;
    }
    return false;
  }
  async dismiss() {
    if (this.containerEl && this.arrowEl && this.trigger) {
      this.balWillAnimate.emit();
      if (this.cleanup) {
        this.cleanup();
      }
      this.trigger.classList.remove('bal-tooltip-trigger');
      hideContainerElement(this.containerEl);
      hideArrowElement(this.arrowEl);
      this.presented = false;
      this.balDidAnimate.emit();
      return true;
    }
    return false;
  }
  async update() {
    if (this.trigger && this.containerEl && this.arrowEl) {
      this.balWillAnimate.emit();
      let isInFrame = false;
      if (balBrowser.hasWindow) {
        isInFrame = !!window.frameElement;
      }
      computePosition(this.trigger, this.containerEl, {
        placement: this.placement,
        middleware: [
          isInFrame ? undefined : shift(),
          flip(),
          offset(8),
          arrow({
            element: this.arrowEl,
            padding: 4,
          }),
        ],
      }).then(({ x, y, middlewareData, placement }) => {
        const side = placement.split('-')[0];
        const staticSide = {
          top: 'bottom',
          right: 'left',
          bottom: 'top',
          left: 'right',
        }[side];
        if (this.containerEl) {
          Object.assign(this.containerEl.style, {
            left: `${x}px`,
            top: `${y}px`,
          });
        }
        if (middlewareData.arrow && this.arrowEl) {
          const arrowPosition = middlewareData.arrow;
          Object.assign(this.arrowEl.style, {
            left: x != null && arrowPosition.x != null ? `${arrowPosition.x}px` : '',
            top: y != null && arrowPosition.y != null ? `${arrowPosition.y}px` : '',
            right: '',
            bottom: '',
            [staticSide]: `${-4}px`,
          });
        }
      });
      this.balDidAnimate.emit();
      return true;
    }
    return false;
  }
  get triggerElement() {
    return document.querySelector(`[id="${this.reference}"]`);
  }
  render() {
    const block = BEM.block('tooltip');
    const containerBlock = block.element('container');
    const arrowBlock = block.element('arrow');
    const innerBlock = block.element('inner');
    const innerContentBlock = innerBlock.element('content');
    return (h(Host, { class: Object.assign({}, block.class()), role: "dialog", "aria-hidden": `${this.presented !== true}`, "aria-modal": `${this.presented === true}`, "aria-presented": `${this.presented === true}` }, h("div", { class: Object.assign({}, containerBlock.class()), ref: containerEl => (this.containerEl = containerEl) }, h("div", { class: Object.assign({}, arrowBlock.class()), ref: arrowEl => (this.arrowEl = arrowEl) }), h("bal-stack", { layout: "vertical", class: Object.assign({}, innerBlock.class()) }, h("div", { class: Object.assign({}, innerContentBlock.class()), ref: contentEl => (this.contentEl = contentEl), "data-test": "bal-tooltip-content" }, h("slot", null))))));
  }
  static get is() { return "bal-tooltip"; }
  static get encapsulation() { return "shadow"; }
  static get originalStyleUrls() {
    return {
      "css": ["bal-tooltip.sass"]
    };
  }
  static get styleUrls() {
    return {
      "css": ["bal-tooltip.css"]
    };
  }
  static get properties() {
    return {
      "reference": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Id of the reference element default is the trigger element."
        },
        "attribute": "reference",
        "reflect": false,
        "defaultValue": "''"
      },
      "placement": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "BalProps.BalTooltipPlacement",
          "resolved": "\"bottom\" | \"left\" | \"right\" | \"top\"",
          "references": {
            "BalProps": {
              "location": "global",
              "id": "global::BalProps"
            }
          }
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "If set it turns a tooltip into a fullscreen or a drawer on touch devices"
        },
        "attribute": "placement",
        "reflect": false,
        "defaultValue": "'bottom'"
      },
      "offset": {
        "type": "number",
        "mutable": false,
        "complexType": {
          "original": "number",
          "resolved": "number",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Offset form trigger to tooltip."
        },
        "attribute": "offset",
        "reflect": false,
        "defaultValue": "0"
      },
      "demo": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [{
              "name": "internal",
              "text": undefined
            }],
          "text": ""
        },
        "attribute": "demo",
        "reflect": false,
        "defaultValue": "false"
      },
      "contentWidth": {
        "type": "number",
        "mutable": false,
        "complexType": {
          "original": "number",
          "resolved": "number | undefined",
          "references": {}
        },
        "required": false,
        "optional": true,
        "docs": {
          "tags": [],
          "text": "Defines the width of the content"
        },
        "attribute": "content-width",
        "reflect": false
      }
    };
  }
  static get states() {
    return {
      "presented": {}
    };
  }
  static get events() {
    return [{
        "method": "balWillAnimate",
        "name": "balWillAnimate",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": "Emitted before the animation starts"
        },
        "complexType": {
          "original": "BalEvents.BalTooltipWillAnimateDetail",
          "resolved": "boolean",
          "references": {
            "BalEvents": {
              "location": "global",
              "id": "global::BalEvents"
            }
          }
        }
      }, {
        "method": "balDidAnimate",
        "name": "balDidAnimate",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": "Emitted after the animation has finished"
        },
        "complexType": {
          "original": "BalEvents.BalTooltipDidAnimateDetail",
          "resolved": "boolean",
          "references": {
            "BalEvents": {
              "location": "global",
              "id": "global::BalEvents"
            }
          }
        }
      }];
  }
  static get methods() {
    return {
      "present": {
        "complexType": {
          "signature": "() => Promise<boolean>",
          "parameters": [],
          "references": {
            "Promise": {
              "location": "global",
              "id": "global::Promise"
            },
            "BalProps": {
              "location": "global",
              "id": "global::BalProps"
            }
          },
          "return": "Promise<boolean>"
        },
        "docs": {
          "text": "",
          "tags": [{
              "name": "internal",
              "text": undefined
            }]
        }
      },
      "dismiss": {
        "complexType": {
          "signature": "() => Promise<boolean>",
          "parameters": [],
          "references": {
            "Promise": {
              "location": "global",
              "id": "global::Promise"
            }
          },
          "return": "Promise<boolean>"
        },
        "docs": {
          "text": "",
          "tags": [{
              "name": "internal",
              "text": undefined
            }]
        }
      },
      "update": {
        "complexType": {
          "signature": "() => Promise<boolean>",
          "parameters": [],
          "references": {
            "Promise": {
              "location": "global",
              "id": "global::Promise"
            }
          },
          "return": "Promise<boolean>"
        },
        "docs": {
          "text": "",
          "tags": [{
              "name": "internal",
              "text": undefined
            }]
        }
      }
    };
  }
  static get elementRef() { return "el"; }
  static get watchers() {
    return [{
        "propName": "contentWidth",
        "methodName": "contentWidthChanged"
      }];
  }
}
__decorate([
  Logger('bal-tooltip')
], Tooltip.prototype, "createLogger", null);
let tooltipIds = 0;
