export class Tooltip {
    constructor(selectorOrElement, options = {}) {
        this.tooltipElement = null;
        this.arrowElement = null;
        this.showTimeout = null;
        this.hideTimeout = null;
        this.isVisible = false;
        this.clearTimeouts = () => {
            if (this.showTimeout) {
                clearTimeout(this.showTimeout);
                this.showTimeout = null;
            }
            if (this.hideTimeout) {
                clearTimeout(this.hideTimeout);
                this.hideTimeout = null;
            }
        };
        this.handleMouseEnter = () => {
            this.show();
        };
        this.handleMouseLeave = () => {
            this.hide();
        };
        this.handleFocus = () => {
            this.show();
        };
        this.handleBlur = () => {
            this.hide();
        };
        this.handleClick = (event) => {
            event.preventDefault();
            this.toggle();
        };
        this.triggerElement =
            typeof selectorOrElement === "string"
                ? document.querySelector(selectorOrElement)
                : selectorOrElement;
        const triggers = options.trigger
            ? Array.isArray(options.trigger)
                ? options.trigger
                : [options.trigger]
            : ["hover", "focus"];
        this.options = {
            content: options.content ??
                this.triggerElement?.getAttribute("title") ??
                "",
            position: options.position ?? "top",
            trigger: triggers,
            showDelay: options.showDelay ?? 200,
            hideDelay: options.hideDelay ?? 100,
            animationDuration: options.animationDuration ?? 150,
            offset: options.offset ?? 8,
            tooltipClass: options.tooltipClass ?? "tooltip__popup",
            maxWidth: options.maxWidth ?? 250,
            allowHTML: options.allowHTML ?? false,
            interactive: options.interactive ?? false,
            arrow: options.arrow ?? true,
            zIndex: options.zIndex ?? 9999,
        };
        if (!this.triggerElement) {
            console.warn("[Stylescape] Tooltip trigger element not found");
            return;
        }
        if (this.triggerElement.hasAttribute("title")) {
            this.triggerElement.removeAttribute("title");
        }
        this.init();
    }
    show() {
        if (!this.triggerElement)
            return;
        this.clearTimeouts();
        this.showTimeout = setTimeout(() => {
            this.createTooltip();
            this.position();
            this.tooltipElement?.classList.add(`${this.options.tooltipClass}--visible`);
            this.isVisible = true;
        }, this.options.showDelay);
    }
    hide() {
        this.clearTimeouts();
        this.hideTimeout = setTimeout(() => {
            this.tooltipElement?.classList.remove(`${this.options.tooltipClass}--visible`);
            setTimeout(() => {
                this.destroyTooltip();
                this.isVisible = false;
            }, this.options.animationDuration);
        }, this.options.hideDelay);
    }
    toggle() {
        if (this.isVisible) {
            this.hide();
        }
        else {
            this.show();
        }
    }
    setContent(content) {
        this.options.content = content;
        if (this.tooltipElement) {
            const contentEl = this.tooltipElement.querySelector(`.${this.options.tooltipClass}__content`);
            if (contentEl) {
                if (this.options.allowHTML) {
                    contentEl.innerHTML = content;
                }
                else {
                    contentEl.textContent = content;
                }
            }
        }
    }
    setPosition(position) {
        this.options.position = position;
        if (this.tooltipElement) {
            this.position();
        }
    }
    get visible() {
        return this.isVisible;
    }
    destroy() {
        this.clearTimeouts();
        this.destroyTooltip();
        this.removeEventListeners();
        this.triggerElement = null;
    }
    static initTooltips() {
        const tooltips = [];
        document
            .querySelectorAll('[data-ss="tooltip"]')
            .forEach((el) => {
            const content = el.dataset.ssTooltipContent ||
                el.getAttribute("title") ||
                "";
            const position = el.dataset.ssTooltipPosition || "top";
            const trigger = el.dataset.ssTooltipTrigger?.split(",") || ["hover", "focus"];
            tooltips.push(new Tooltip(el, {
                content,
                position,
                trigger,
            }));
        });
        return tooltips;
    }
    init() {
        if (!this.triggerElement)
            return;
        const id = `tooltip-${Date.now()}-${Math.random().toString(36).slice(2)}`;
        this.triggerElement.setAttribute("aria-describedby", id);
        const triggers = this.options.trigger;
        if (triggers.includes("hover")) {
            this.triggerElement.addEventListener("mouseenter", this.handleMouseEnter);
            this.triggerElement.addEventListener("mouseleave", this.handleMouseLeave);
        }
        if (triggers.includes("focus")) {
            this.triggerElement.addEventListener("focus", this.handleFocus);
            this.triggerElement.addEventListener("blur", this.handleBlur);
        }
        if (triggers.includes("click")) {
            this.triggerElement.addEventListener("click", this.handleClick);
        }
    }
    removeEventListeners() {
        if (!this.triggerElement)
            return;
        this.triggerElement.removeEventListener("mouseenter", this.handleMouseEnter);
        this.triggerElement.removeEventListener("mouseleave", this.handleMouseLeave);
        this.triggerElement.removeEventListener("focus", this.handleFocus);
        this.triggerElement.removeEventListener("blur", this.handleBlur);
        this.triggerElement.removeEventListener("click", this.handleClick);
    }
    createTooltip() {
        if (this.tooltipElement)
            return;
        const tooltip = document.createElement("div");
        tooltip.className = this.options.tooltipClass;
        tooltip.setAttribute("role", "tooltip");
        tooltip.setAttribute("id", this.triggerElement?.getAttribute("aria-describedby") || "");
        tooltip.style.zIndex = String(this.options.zIndex);
        tooltip.style.maxWidth = `${this.options.maxWidth}px`;
        const content = document.createElement("div");
        content.className = `${this.options.tooltipClass}__content`;
        if (this.options.allowHTML) {
            content.innerHTML = this.options.content;
        }
        else {
            content.textContent = this.options.content;
        }
        tooltip.appendChild(content);
        if (this.options.arrow) {
            this.arrowElement = document.createElement("div");
            this.arrowElement.className = `${this.options.tooltipClass}__arrow`;
            tooltip.appendChild(this.arrowElement);
        }
        if (this.options.interactive) {
            tooltip.addEventListener("mouseenter", this.clearTimeouts);
            tooltip.addEventListener("mouseleave", () => this.hide());
        }
        document.body.appendChild(tooltip);
        this.tooltipElement = tooltip;
    }
    destroyTooltip() {
        this.tooltipElement?.remove();
        this.tooltipElement = null;
        this.arrowElement = null;
    }
    position() {
        if (!this.triggerElement || !this.tooltipElement)
            return;
        const triggerRect = this.triggerElement.getBoundingClientRect();
        const tooltipRect = this.tooltipElement.getBoundingClientRect();
        const scrollX = window.scrollX;
        const scrollY = window.scrollY;
        let position = this.options.position;
        if (position === "auto") {
            position = this.calculateBestPosition(triggerRect, tooltipRect);
        }
        let top;
        let left;
        switch (position) {
            case "top":
                top =
                    triggerRect.top +
                        scrollY -
                        tooltipRect.height -
                        this.options.offset;
                left =
                    triggerRect.left +
                        scrollX +
                        (triggerRect.width - tooltipRect.width) / 2;
                break;
            case "bottom":
                top = triggerRect.bottom + scrollY + this.options.offset;
                left =
                    triggerRect.left +
                        scrollX +
                        (triggerRect.width - tooltipRect.width) / 2;
                break;
            case "left":
                top =
                    triggerRect.top +
                        scrollY +
                        (triggerRect.height - tooltipRect.height) / 2;
                left =
                    triggerRect.left +
                        scrollX -
                        tooltipRect.width -
                        this.options.offset;
                break;
            case "right":
                top =
                    triggerRect.top +
                        scrollY +
                        (triggerRect.height - tooltipRect.height) / 2;
                left = triggerRect.right + scrollX + this.options.offset;
                break;
            default:
                top =
                    triggerRect.top +
                        scrollY -
                        tooltipRect.height -
                        this.options.offset;
                left =
                    triggerRect.left +
                        scrollX +
                        (triggerRect.width - tooltipRect.width) / 2;
        }
        left = Math.max(8, Math.min(left, window.innerWidth - tooltipRect.width - 8));
        this.tooltipElement.style.top = `${top}px`;
        this.tooltipElement.style.left = `${left}px`;
        this.tooltipElement.dataset.position = position;
        if (this.arrowElement) {
            this.arrowElement.dataset.position = position;
        }
    }
    calculateBestPosition(triggerRect, tooltipRect) {
        const space = {
            top: triggerRect.top,
            bottom: window.innerHeight - triggerRect.bottom,
            left: triggerRect.left,
            right: window.innerWidth - triggerRect.right,
        };
        const height = tooltipRect.height + this.options.offset;
        const width = tooltipRect.width + this.options.offset;
        if (space.top >= height)
            return "top";
        if (space.bottom >= height)
            return "bottom";
        if (space.right >= width)
            return "right";
        if (space.left >= width)
            return "left";
        return "top";
    }
}
export default Tooltip;
//# sourceMappingURL=Tooltip.js.map