import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
    static targets = ["initialFocus"];

    connect() {
        this.ageGateRoot = this.element.closest('[data-controller~="live"]') ?? this.element;
        this.previousBodyOverflow = document.body.style.overflow;
        this.backgroundStates = new Map();

        document.body.style.overflow = "hidden";
        this.disableBackground();
        this.focusInitialControl();
        this.element.addEventListener("keydown", this.trapFocus);
    }

    disconnect() {
        document.body.style.overflow = this.previousBodyOverflow;
        this.restoreBackground();
        this.element.removeEventListener("keydown", this.trapFocus);
    }

    disableBackground() {
        for (const child of document.body.children) {
            if (child === this.ageGateRoot || child.tagName === "SCRIPT") {
                continue;
            }

            this.backgroundStates.set(child, {
                inert: child.inert,
                ariaHidden: child.getAttribute("aria-hidden"),
            });
            child.inert = true;
            child.setAttribute("aria-hidden", "true");
        }
    }

    restoreBackground() {
        for (const [child, state] of this.backgroundStates) {
            child.inert = state.inert;
            if (state.ariaHidden === null) {
                child.removeAttribute("aria-hidden");
            } else {
                child.setAttribute("aria-hidden", state.ariaHidden);
            }
        }

        this.backgroundStates.clear();
    }

    focusInitialControl() {
        window.requestAnimationFrame(() => {
            const control = this.hasInitialFocusTarget
                ? this.initialFocusTarget
                : this.focusableElements[0];
            control?.focus({ preventScroll: true });
        });
    }

    normalizeYear(event) {
        event.currentTarget.value = event.currentTarget.value.replace(/\D/g, "").slice(0, 4);
    }

    changeLanguage(event) {
        const url = new URL(event.currentTarget.value, window.location.origin);
        if (url.origin === window.location.origin) {
            window.location.assign(url.href);
        }
    }

    trapFocus = (event) => {
        if (event.key !== "Tab") {
            return;
        }

        const focusableElements = this.focusableElements;
        if (focusableElements.length === 0) {
            event.preventDefault();
            return;
        }

        const first = focusableElements[0];
        const last = focusableElements[focusableElements.length - 1];

        if (event.shiftKey && document.activeElement === first) {
            event.preventDefault();
            last.focus();
        } else if (!event.shiftKey && document.activeElement === last) {
            event.preventDefault();
            first.focus();
        }
    };

    get focusableElements() {
        return Array.from(this.element.querySelectorAll(
            'button:not([disabled]), select:not([disabled]), input:not([disabled]), textarea:not([disabled]), a[href], [tabindex]:not([tabindex="-1"])',
        )).filter((element) => !element.hidden);
    }
}
