const FxTooltip = (() => {
    let tooltipEl = null;
    let arrowEl = null;
    let innerEl = null;
    let currentTarget = null;
    let hideTimeout = null;
    let lastTitle = null;
    let openedViaClick = false;
    let isHoveringTooltip = false;
    let activeRootNode = null;
    const isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
    function createTooltipElement(rootNode) {
        if (tooltipEl && activeRootNode === rootNode) {
            if (!tooltipEl.isConnected) {
                tooltipEl = null;
            } else {
                return;
            }
        }
        if (tooltipEl && activeRootNode !== rootNode) {
            tooltipEl.remove();
            tooltipEl = null;
        }
        tooltipEl = document.createElement("div");
        tooltipEl.className = "fx-tooltip";
        tooltipEl.innerHTML = '<div class="fx-tooltip-arrow"></div><div class="fx-tooltip-inner"></div>';
        if (rootNode instanceof ShadowRoot) {
            rootNode.appendChild(tooltipEl);
        } else {
            document.body.appendChild(tooltipEl);
        }
        activeRootNode = rootNode;
        arrowEl = tooltipEl.querySelector(".fx-tooltip-arrow");
        innerEl = tooltipEl.querySelector(".fx-tooltip-inner");
        tooltipEl.addEventListener("mouseenter", () => {
            if (currentTarget && currentTarget.getAttribute("data-tooltip-hoverable") === "true") {
                isHoveringTooltip = true;
                if (hideTimeout) {
                    clearTimeout(hideTimeout);
                    hideTimeout = null;
                }
            }
        });
        tooltipEl.addEventListener("mouseleave", () => {
            isHoveringTooltip = false;
            if (currentTarget && !openedViaClick) {
                hide();
            }
        });
    }
    function show(target) {
        if (!target) return;
        if (hideTimeout) {
            clearTimeout(hideTimeout);
            hideTimeout = null;
        }
        const title = target.getAttribute("data-tooltip-title") || target.getAttribute("title") || "";
        if (!title.trim()) return;
        const rootNode = target.getRootNode();
        createTooltipElement(rootNode);
        if (target.hasAttribute("title")) {
            target.setAttribute("data-tooltip-title", title);
            target.removeAttribute("title");
        }
        const isHtml = target.getAttribute("data-tooltip-html") === "true";
        if (target === currentTarget && tooltipEl.classList.contains("show")) {
            if (title === lastTitle) {
                return;
            }
            lastTitle = title;
            if (isHtml) {
                innerEl.innerHTML = title;
            } else {
                innerEl.textContent = title;
            }
            const placement = target.getAttribute("data-tooltip-placement") || "top";
            tooltipEl.className = "fx-tooltip show";
            positionTooltip(target, placement);
            return;
        }
        currentTarget = target;
        lastTitle = title;
        if (isHtml) {
            innerEl.innerHTML = title;
        } else {
            innerEl.textContent = title;
        }
        const placement = target.getAttribute("data-tooltip-placement") || "top";
        tooltipEl.style.position = "fixed";
        tooltipEl.style.top = "-9999px";
        tooltipEl.style.left = "-9999px";
        tooltipEl.style.visibility = "hidden";
        tooltipEl.style.display = "block";
        tooltipEl.className = "fx-tooltip";
        void tooltipEl.offsetHeight;
        positionTooltip(target, placement);
        tooltipEl.style.visibility = "visible";
        tooltipEl.classList.add("show");
    }
    function positionTooltip(target, preferredPlacement) {
        const targetRect = target.getBoundingClientRect();
        if (!targetRect.width && !targetRect.height) {
            tooltipEl.style.display = "none";
            return;
        }
        const tooltipWidth = tooltipEl.offsetWidth;
        const tooltipHeight = tooltipEl.offsetHeight;
        const gap = 8;
        const edgePadding = 10;
        const offsetY = 0;
        const offsetX = 0;
        const boundsLeft = 0;
        const boundsTop = 0;
        const boundsRight = window.innerWidth;
        const boundsBottom = window.innerHeight;
        const spaceTop = targetRect.top - boundsTop;
        const spaceBottom = boundsBottom - targetRect.bottom;
        const spaceLeft = targetRect.left - boundsLeft;
        const spaceRight = boundsRight - targetRect.right;
        const targetCenterX = targetRect.left + targetRect.width / 2;
        const canFitHorizontally = targetCenterX - tooltipWidth / 2 >= boundsLeft + edgePadding && targetCenterX + tooltipWidth / 2 <= boundsRight - edgePadding;
        let placement = preferredPlacement;
        if (placement === "top" || placement === "bottom") {
            const hasVerticalSpace = placement === "top" ? spaceTop >= tooltipHeight + gap : spaceBottom >= tooltipHeight + gap;
            if (hasVerticalSpace && !canFitHorizontally) {
                if (spaceRight >= tooltipWidth + gap) {
                    placement = "right";
                } else if (spaceLeft >= tooltipWidth + gap) {
                    placement = "left";
                }
            } else if (!hasVerticalSpace) {
                const oppositeHasSpace = placement === "top" ? spaceBottom >= tooltipHeight + gap : spaceTop >= tooltipHeight + gap;
                if (oppositeHasSpace && canFitHorizontally) {
                    placement = placement === "top" ? "bottom" : "top";
                } else if (spaceRight >= tooltipWidth + gap) {
                    placement = "right";
                } else if (spaceLeft >= tooltipWidth + gap) {
                    placement = "left";
                } else if (oppositeHasSpace) {
                    placement = placement === "top" ? "bottom" : "top";
                }
            }
        } else if (placement === "left") {
            if (spaceLeft < tooltipWidth + gap) {
                if (spaceRight >= tooltipWidth + gap) {
                    placement = "right";
                } else if (spaceTop >= tooltipHeight + gap) {
                    placement = "top";
                } else if (spaceBottom >= tooltipHeight + gap) {
                    placement = "bottom";
                }
            }
        } else if (placement === "right") {
            if (spaceRight < tooltipWidth + gap) {
                if (spaceLeft >= tooltipWidth + gap) {
                    placement = "left";
                } else if (spaceTop >= tooltipHeight + gap) {
                    placement = "top";
                } else if (spaceBottom >= tooltipHeight + gap) {
                    placement = "bottom";
                }
            }
        }
        let top, left;
        switch (placement) {
          case "top":
            top = targetRect.top + offsetY - tooltipHeight - gap;
            left = targetRect.left + offsetX + targetRect.width / 2 - tooltipWidth / 2;
            break;

          case "bottom":
            top = targetRect.bottom + offsetY + gap;
            left = targetRect.left + offsetX + targetRect.width / 2 - tooltipWidth / 2;
            break;

          case "left":
            top = targetRect.top + offsetY + targetRect.height / 2 - tooltipHeight / 2;
            left = targetRect.left + offsetX - tooltipWidth - gap;
            break;

          case "right":
            top = targetRect.top + offsetY + targetRect.height / 2 - tooltipHeight / 2;
            left = targetRect.right + offsetX + gap;
            break;
        }
        const leftMin = offsetX + boundsLeft + edgePadding;
        const leftMax = offsetX + boundsRight - tooltipWidth - edgePadding;
        if (left < leftMin) {
            left = leftMin;
        } else if (left > leftMax) {
            left = leftMax;
        }
        const topMin = offsetY + boundsTop + edgePadding;
        if (top < topMin) {
            top = topMin;
        }
        if (placement === "top" || placement === "bottom") {
            const targetCenterXAbs = targetRect.left + offsetX + targetRect.width / 2;
            const arrowLeft = targetCenterXAbs - left - 6;
            arrowEl.style.left = Math.max(12, Math.min(arrowLeft, tooltipWidth - 24)) + "px";
        } else {
            arrowEl.style.left = "";
        }
        tooltipEl.style.top = top + "px";
        tooltipEl.style.left = left + "px";
        tooltipEl.classList.add("fx-tooltip-" + placement);
    }
    function hide(immediate = false) {
        if (immediate) {
            if (hideTimeout) {
                clearTimeout(hideTimeout);
                hideTimeout = null;
            }
            if (tooltipEl) {
                tooltipEl.classList.remove("show");
                tooltipEl.style.display = "none";
            }
            currentTarget = null;
            lastTitle = null;
            openedViaClick = false;
            return;
        }
        const targetToHide = currentTarget;
        hideTimeout = setTimeout(() => {
            if (currentTarget === targetToHide) {
                if (tooltipEl) {
                    tooltipEl.classList.remove("show");
                    tooltipEl.style.display = "none";
                }
                currentTarget = null;
                lastTitle = null;
                openedViaClick = false;
            }
            hideTimeout = null;
        }, 100);
    }
    function init(rootNode = document) {
        const guardKey = "__fxTooltipInitialized";
        if (rootNode === document) {
            if (window[guardKey]) return;
            window[guardKey] = true;
        } else {
            if (rootNode[guardKey]) return;
            rootNode[guardKey] = true;
        }
        rootNode.addEventListener("mouseover", e => {
            if (!e.target || typeof e.target.closest !== "function") return;
            const target = e.target.closest("[data-tooltip-title]");
            if (!target) {
                if (tooltipEl && tooltipEl.contains(e.target)) {
                    if (currentTarget && currentTarget.getAttribute("data-tooltip-hoverable") === "true") {
                        if (hideTimeout) {
                            clearTimeout(hideTimeout);
                            hideTimeout = null;
                        }
                        return;
                    }
                }
                if (currentTarget && !openedViaClick && !isHoveringTooltip) {
                    hide();
                }
                return;
            }
            if (isTouchDevice) {
                return;
            }
            if (target.getAttribute("data-tooltip-trigger") === "click-only") {
                return;
            }
            if (openedViaClick) {
                return;
            }
            if (hideTimeout) {
                clearTimeout(hideTimeout);
                hideTimeout = null;
            }
            if (target === currentTarget && tooltipEl && tooltipEl.classList.contains("show")) {
                return;
            }
            if (target.getAttribute("data-tooltip-overflow") === "true") {
                if (target.scrollWidth > target.clientWidth) {
                    show(target);
                } else {
                    target.removeAttribute("data-tooltip-title");
                    target.removeAttribute("data-tooltip-overflow");
                }
            } else {
                show(target);
            }
        });
        rootNode.addEventListener("mouseout", e => {
            if (!currentTarget) return;
            if (openedViaClick) return;
            if (isTouchDevice) return;
            if (!e.relatedTarget) {
                hide();
            }
        });
        rootNode.addEventListener("click", e => {
            if (!e.target || typeof e.target.closest !== "function") return;
            const clickOnlyTarget = e.target.closest('[data-tooltip-trigger="click-only"]');
            const clickTarget = e.target.closest('[data-tooltip-trigger="click"]');
            const target = clickOnlyTarget || (isTouchDevice ? clickTarget : null);
            if (target) {
                e.preventDefault();
                e.stopPropagation();
                if (target === currentTarget && tooltipEl && tooltipEl.classList.contains("show")) {
                    hide(true);
                    openedViaClick = false;
                } else {
                    if (target.getAttribute("data-tooltip-overflow") === "true") {
                        if (target.scrollWidth > target.clientWidth) {
                            show(target);
                            openedViaClick = true;
                        } else {
                            target.removeAttribute("data-tooltip-title");
                            target.removeAttribute("data-tooltip-overflow");
                        }
                    } else {
                        show(target);
                        openedViaClick = true;
                    }
                }
                return;
            }
            if (currentTarget && openedViaClick) {
                if (tooltipEl && !tooltipEl.contains(e.target) && !currentTarget.contains(e.target)) {
                    hide(true);
                    openedViaClick = false;
                }
            }
        });
        if (rootNode === document) {
            document.addEventListener("scroll", () => {
                if (currentTarget) hide(true);
            }, {
                passive: true
            });
        } else {
            rootNode.addEventListener("scroll", () => {
                if (currentTarget) hide(true);
            }, {
                capture: true,
                passive: true
            });
            window.addEventListener("scroll", () => {
                if (currentTarget && activeRootNode === rootNode) hide(true);
            }, {
                passive: true
            });
        }
    }
    return {
        init: init,
        show: show,
        hide: hide
    };
})();

function initializeTooltips(rootNode = document) {
    FxTooltip.init(rootNode);
}

export { FxTooltip, initializeTooltips };

if (typeof window !== "undefined") {
    window.FxTooltip = FxTooltip;
}