import { Context } from "../engine_setup.js";
import { DeviceUtilities, getParam } from "../engine_utils.js";

const debug = getParam("debugoverlay");
export const arContainerClassName = "ar";
export const quitARClassName = "quit-ar";

// https://developers.google.com/web/fundamentals/web-components/customelements
/** @internal */
export class AROverlayHandler {

    get ARContainer(): HTMLElement | null { return this.arContainer; }

    private arContainer: HTMLElement | null = null;
    currentSession: XRSession | null = null;

    private _createdAROnlyElements: Array<any> = [];
    private _reparentedObjects: Array<{ el: Element, previousParent: HTMLElement | null }> = [];
    private contentElement: HTMLElement | null = null;
    private originalDomOverlayParent: ParentNode | null = null;


    requestEndAR = () => {
        this.onRequestedEndAR();
    }

    onBegin(context: Context, overlayContainer: HTMLElement, session: XRSession) {
        this.currentSession = session;
        this.arContainer = overlayContainer;

        if (DeviceUtilities.isMozillaXR() || DeviceUtilities.isNeedleAppClip()) {
            const arElements = context.domElement!.children;
            for (let i = 0; i < arElements?.length; i++) {
                const el = arElements[i];
                if (!el) return;
                if (el === this.arContainer) return;
                this._reparentedObjects.push({ el: el, previousParent: el.parentElement });
                this.arContainer?.appendChild(el);
            }

            if (overlayContainer) {
                this.originalDomOverlayParent = overlayContainer.parentNode;
                if (this.originalDomOverlayParent) {
                    console.log("Reparent DOM Overlay to body", overlayContainer, overlayContainer.style.display);
                    // mozilla webxr does hide elements on session start
                    // this is only necessary if we generated the overlay element
                    overlayContainer.style.display = "";
                    overlayContainer.style.visibility = "";
                    document.body.appendChild(overlayContainer);
                }
            }
            else {
                console.warn("WebXRViewer: No DOM Overlay found");
            }
        }
        this.ensureQuitARButton(this.arContainer);
    }

    onEnd(_context: Context) {
        // if (this.arContainer)
        // this.arContainer.classList.remove("ar-session-active");
        for (const created of this._createdAROnlyElements) {
            if (created.remove) {
                created.remove();
            }
        }

        for (const prev of this._reparentedObjects) {
            const el = prev.el as HTMLElement;
            prev.previousParent?.appendChild(el);
        }
        this._reparentedObjects.length = 0;

        // mozilla XR exit AR fixes
        if (DeviceUtilities.isMozillaXR()) {
            // without the timeout we get errors in mozillas code and can not enter XR again
            // not sure why we have to wait
            setTimeout(() => {
                // Canvas is not in DOM anymore after AR using Mozilla XR
                const canvas = _context.renderer.domElement;
                if (canvas) {
                    _context.domElement.shadowRoot?.prepend(canvas);
                }

                // Fix visibility
                const elements = document.querySelectorAll("*");
                for (var i = 0; i < elements.length; i++) {
                    const child = elements[i] as any;
                    if (child && child._displayChanged !== undefined && child._displayWas !== undefined) {
                        child.style.display = child._displayWas;
                    }
                }
            }, 10);
        }
    }


    createOverlayContainer(needleEngineElement: HTMLElement): HTMLElement {
        if (this.contentElement) return this.contentElement;

        if (debug)
            console.log("Setup overlay container");

        const contentElement = needleEngineElement.shadowRoot!.querySelector(".content") as HTMLElement;
        this.contentElement = contentElement;

        const overlaySlot = needleEngineElement.shadowRoot!.querySelector(".overlay-content");
        if (overlaySlot) contentElement.appendChild(overlaySlot);
        if (debug && !DeviceUtilities.isMobileDevice()) this.ensureQuitARButton(contentElement);
        return contentElement;
    }

    private onRequestedEndAR() {
        if (!this.currentSession) return;
        this.currentSession.end();
        this.currentSession = null;
    }

    private ensureQuitARButton(element: HTMLElement) {


        const quitARSlot = document.createElement("slot");
        quitARSlot.style.display = "contents";
        quitARSlot.style.padding = "10px";
        quitARSlot.setAttribute("name", "quit-ar");
        this.appendElement(quitARSlot, element);
        this._createdAROnlyElements.push(quitARSlot);
        // for mozilla XR reparenting we have to make sure the close button is clickable so we set it on the element directly
        // it's in general perhaps more safe to set it on the element to ensure it's clickable
        quitARSlot.style.pointerEvents = "auto";
        // No default quit button in the top right corner in app clips
        // we provide one via the native UI
        if (DeviceUtilities.isNeedleAppClip()) {

            // quitARSlot.style.display = "none";
            globalThis["NEEDLE_ENGINE_APPCLIP_DISABLE_MENU"] = true;

            // respect the UI bar at the top of the screen and add some padding to the quit button container
            // @TODO: this should be done in CSS in one place and not here and in debug overlay
            const meta = document.querySelector('meta[name="viewport"]');
            if (meta && !meta.getAttribute("content")?.includes("viewport-fit=")) {
                meta.setAttribute("content", meta.getAttribute("content") + ",viewport-fit=cover");
            }
        }

        // We want to search the document if there's a quit-ar button
        // In which case we don't want to populate the default button (slot) with any content
        const quitARElement = document.querySelector(`.${quitARClassName}`);
        if (quitARElement) {
            quitARElement.addEventListener('click', this.requestEndAR);
            if (debug) quitARElement.addEventListener('click', () => console.log("Clicked quit-ar button"));
            // We found a explicit quit-ar element
            return;
        }

        quitARSlot.addEventListener('click', this.requestEndAR);
        if (debug) quitARSlot.addEventListener('click', () => console.log("Clicked fallback close button"));

        // we need another container to make sure the button is always on top
        const fixedButtonContainer = document.createElement("div");
        fixedButtonContainer.style.cssText = `
            position: fixed;
            top: 0;
            right: 0;
            z-index: 600;
            pointer-events: all;
            padding-top: env(safe-area-inset-top, 0px);
            padding-right: calc(env(safe-area-inset-right, 0px) + 10px);
        `;
        this.appendElement(fixedButtonContainer, quitARSlot);

        var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
        svg.classList.add("quit-ar-button");
        svg.setAttribute('width', "40px");
        svg.setAttribute('height', "40px");
        svg.style.cssText = `
            background: rgba(255, 255, 255, .4);
            -webkit-backdrop-filter: blur(8px);
            backdrop-filter: blur(8px);
            border-radius: 50%;
            box-shadow: 0 0 5px rgba(0,0,0,.3);
            outline: 1px solid rgba(255, 255, 255, .6);
            display: flex;
            justify-content: center;
            align-items: center;
        `;
        fixedButtonContainer.appendChild(svg);

        var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
        path.setAttribute('d', 'M 12,12 L 28,28 M 28,12 12,28');
        path.setAttribute('stroke', '#000000');
        path.setAttribute('stroke-width', "2px");
        path.style.cssText = `
            /**filter: drop-shadow(0 0px 1.2px rgba(0,0,0,.7));**/
        `
        svg.appendChild(path);
        if (debug) console.log("Created fallback close button", svg, element);
    }

    private appendElement(element: Element, parent: HTMLElement) {
        if (parent.shadowRoot) return parent.shadowRoot.appendChild(element);
        return parent.appendChild(element);
    }

}
