import { isDevEnvironment } from "../debug/index.js";
import { ButtonsFactory } from "./buttons.js";
import { iconFontUrl, loadFont } from "./fonts.js";
import { WebXRButtonFactory } from "./WebXRButtons.js";

declare global {
    interface HTMLElementTagNameMap {
        "needle-button": NeedleButtonElement;
    }
}

const htmlTagName = "needle-button";
const isDev = isDevEnvironment();

/**
 * [&lt;needle-button&gt;](https://engine.needle.tools/docs/api/NeedleButtonElement) is a web component for easily adding AR, VR, Quicklook, or QR code buttons to your website without writing JavaScript code.
 *
 * The button automatically handles session management and displays appropriate UI based on device capabilities.
 * It comes with default styling (glassmorphism design) but can be fully customized with CSS.
 *
 * **Supported button types:**
 * - `ar` - WebXR AR session button
 * - `vr` - WebXR VR session button
 * - `quicklook` - Apple AR Quick Look button (iOS only)
 * - `qrcode` - QR code sharing button
 *
 * @example Basic AR/VR buttons
 * ```html
 * <needle-engine src="scene.glb"></needle-engine>
 * <needle-button ar></needle-button>
 * <needle-button vr></needle-button>
 * <needle-button quicklook></needle-button>
 * ```
 *
 * @example Custom button labels
 * ```html
 * <needle-button ar>Start AR Experience</needle-button>
 * <needle-button vr>Enter VR Mode</needle-button>
 * <needle-button quicklook>View in AR</needle-button>
 * ```
 *
 * @example Custom styling
 * ```html
 * <style>
 *   needle-button {
 *     background-color: #ff6b6b;
 *     color: white;
 *     border-radius: 8px;
 *     padding: 1rem 2rem;
 *   }
 *   needle-button:hover {
 *     background-color: #ff5252;
 *   }
 * </style>
 * <needle-button ar>Start AR</needle-button>
 * ```
 *
 * @example Unstyled button (for complete custom styling)
 * ```html
 * <needle-button ar unstyled>
 *   <span class="my-icon">🥽</span>
 *   Launch AR
 * </needle-button>
 * ```
 *
 * @see {@link NeedleEngineWebComponent} for the main &lt;needle-engine&gt; element
 * @see {@link NeedleMenu} for the built-in menu component that can display similar buttons
 */
export class NeedleButtonElement extends HTMLElement {

    static observedAttributes = ["ar", "vr", "quicklook", "qrcode"];

    constructor() {
        super();
        this.removeEventListener("click", this.#onclick);
        this.addEventListener("click", this.#onclick);
    }

    attributeChangedCallback(_name: string, _oldValue: string, _newValue: string) {
        this.#update()
    }

    #root!: ShadowRoot;
    #slot!: HTMLSlotElement;
    /** These are the default styles that can be overridden by the user from the outside by styling <needle-button> */
    #styles!: HTMLStyleElement;

    /** This is the button that was generated using one of the factories */
    #button: HTMLButtonElement | undefined;
    /** If AR or VR is requested we create and use the webxr button factory to create a button with default behaviour */
    #webxrfactory: WebXRButtonFactory | undefined;
    #buttonfactory: ButtonsFactory | undefined;

    #observer: MutationObserver | undefined;

    #update() {
        this.#button?.remove();

        if (this.getAttribute("ar") != null) {
            this.#webxrfactory ??= new WebXRButtonFactory()
            this.#button = this.#webxrfactory.createARButton();
            this.setAttribute("aria-label", "Enter augmented reality mode");
        }
        else if (this.getAttribute("vr") != null) {
            this.#webxrfactory ??= new WebXRButtonFactory()
            this.#button = this.#webxrfactory.createVRButton();
            this.setAttribute("aria-label", "Enter virtual reality mode");
        }
        else if (this.getAttribute("quicklook") != null) {
            this.#webxrfactory ??= new WebXRButtonFactory()
            this.#button = this.#webxrfactory.createQuicklookButton();
            this.setAttribute("aria-label", "View in AR with Apple Quick Look");
        }
        else if (this.getAttribute("qrcode") != null) {
            this.#buttonfactory ??= new ButtonsFactory();
            this.#button = this.#buttonfactory.createQRCode({ anchorElement: this });
            this.setAttribute("aria-label", "Share application with QR code");
        }
        else {
            if (isDev) {
                console.warn("No button type specified for <needle-button>. Use either ar, vr or quicklook attribute.")
            }
            else {
                console.debug("No button type specified for <needle-button>. Use either ar, vr or quicklook attribute.")
            }
            this.setAttribute("aria-label", "Needle Button with no specified type");
            return;
        }

        this.#root ??= this.attachShadow({ mode: "open" });
        this.#slot ??= document.createElement("slot");
        this.#styles ??= document.createElement("style");
        this.#styles.innerHTML = `
            button {
                all: unset;
            }
        `;
        const hasUnstyledAttribute = this.getAttribute("unstyled") != undefined;
        if (!hasUnstyledAttribute) {
            this.#styles.innerHTML += `
            :host {
                display: inline-flex;
                align-items: center;
                justify-content: center;
                width: fit-content;

                padding: 0.4rem .5rem;
                border-radius: 100vw;
                
                background: rgba(245, 245, 245, .8);
                backdrop-filter: blur(10px);

                cursor: pointer;
                color: black;
                outline: rgba(0,0,0,.05) 1px solid;

                transition: all .2s;
            }
            :host(:hover) {
                background: rgba(255, 255, 255, 1);
                transition: background .2s;
            }
            slot {
                display: flex;
                align-items: center;
                justify-content: center;
                gap: .5rem;
            }
`
        }

        /**
         * We now structure the results as follows:
         * <button>
         *  <slot>
         *      <original_button_content>
         *  </slot>
         * </button> 
         */
        this.#slot.innerHTML = this.#button.innerHTML;
        this.#slot.style.cssText = `display: flex; align-items: center; justify-content: center;`
        this.#button.innerHTML = this.#slot.outerHTML;
        this.#root.innerHTML = this.#button.outerHTML;
        this.#root.prepend(this.#styles);
        loadFont(iconFontUrl, { element: this.#root });

        this.#observer?.disconnect();
        this.#observer ??= new MutationObserver(() => this.#updateVisibility());
        this.#observer.observe(this.#button, { attributes: true });
        if (isDev) {
            console.log("Needle Button updated", this);
        }
    }

    #updateVisibility() {
        if (this.#button) {
            if (this.#button.style.display === "none") {
                this.style.display = "none";
            }
            else if (this.style.display === "none") {
                this.style.display = "";
            }
        }
    }

    #onclick = (_ev: MouseEvent) => {
        if (isDev) {
            console.log("Needle Button clicked", { defaultPrevented: _ev.defaultPrevented, hasButton: !!this.#button });
        }
        if (_ev.defaultPrevented) return;

        if (this.#button) {
            this.#button.click()
        }

    }

}



if (typeof window !== "undefined" && !window.customElements.get(htmlTagName))
    window.customElements.define(htmlTagName, NeedleButtonElement);