/* ===================== AUTOGENERATED SOURCE IMPORT ===================== */

import Template from "/emcJS/util/html/template/HTMLTemplate.js";

const TPL = new Template(`
    <div id="focus_catcher_top" tabindex="0"></div>
    <emc-ctxmenulayer>
        <div id="window" role="dialog" aria-modal="true" aria-labelledby="title" aria-describedby="title">
            <div id="header">
                <div id="title"></div>
                <button id="close" title="close">
                    <emc-symbol-close></emc-symbol-close>
                </button>
            </div>
            <div id="body">
                <slot></slot>
            </div>
        </div>
    </emc-ctxmenulayer>
    <div id="focus_catcher_bottom" tabindex="0"></div>
`);

import GlobalStyle from "/emcJS/util/html/template/CSSTemplate.js";

const STYLE = new GlobalStyle(`
    :host {
        position: fixed !important;
        box-sizing: border-box !important;
        align-items: flex-start !important;
        justify-content: center !important;
        top: 0 !important;
        left: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
        width: 100% !important;
        height: 100% !important;
        cursor: default !important;
        overflow: hidden !important;
        background-color: rgba(0, 0, 0, 0.3);
        backdrop-filter: blur(2px);
        -webkit-backdrop-filter: blur(2px);
        z-index: var(--z-index-modal, 900600);
        pointer-events: all !important;
    }
    
    :host(.inactive) {
        background-color: transparent !important;
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        z-index: calc(var(--z-index-modal, 900600) - 1);
    }
    
    :host,
    .button {
        display: flex;
    }
    
    #window {
        display: flex;
        flex-direction: column;
        width: auto;
        height: auto;
        min-width: min(400px, calc(100dvw - 50px));
        max-width: min(1000px, calc(100dvw - 50px));
        min-height: min(200px, calc(100dvh - 50px));
        max-height: min(800px, calc(100dvh - 50px));
        margin-top: min(100px, calc(25px + max(0px, calc(55dvh - 480px))));
        color: var(--modal-text-color, #000000);
        background-color: var(--modal-back-color, #ffffff);
        background-image: var(--modal-back-image, none);
        border-style: solid;
        border-width: var(--modal-border-width, 2px);
        border-color: var(--modal-border-color, #cccccc);
        border-radius: 4px;
        resize: both;
        pointer-events: all;
    }
    
    :host(.inactive) #window {
        pointer-events: none;
        filter: blur(2px);
    }
    
    #header {
        display: flex;
        color: var(--modal-header-text-color, #000000);
        background-color: var(--modal-header-back-color, #e4e4e4);
        background-image: var(--modal-header-back-image, none);
        border-bottom: solid var(--modal-border-width, 2px) var(--modal-border-color, #cccccc);
    }
    
    #title {
        display: flex;
        align-items: center;
        flex: 1;
        height: 30px;
        padding: 0 10px;
        font-weight: bold;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-size: 1em;
        line-height: 1em;
    }
    
    #body {
        display: flex;
        flex-direction: column;
        flex: 1;
        overflow: auto;
    }
    
    :focus {
        box-shadow: 0 0 2px 2px var(--input-focus-color, #06b5ff);
        outline: none;
    }
    
    :focus:not(:focus-visible) {
        box-shadow: none;
        outline: none;
    }
    
    #close {
        display: flex;
        width: 40px;
        height: 30px;
        border: none;
        align-items: center;
        justify-content: center;
        color: var(--modal-close-text-color, #222222);
        background-color: var(--modal-close-back-color, #ffb9b9);
        background-image: var(--modal-close-back-image, none);
        cursor: pointer;
        appearance: none;
        font-size: 1.2em;
        line-height: 1em;
    }
    
    #close:hover {
        color: var(--modal-close-hover-text-color, #ffffff);
        background-color: var(--modal-close-hover-back-color, #ff0000);
        background-image: var(--modal-close-hover-back-image, none);
    }
    
    #close:focus {
        box-shadow: inset var(--modal-close-focus-color, #000000) 0 0px 3px 4px;
        outline: none;
    }
    
    #close:focus:not(:focus-visible) {
        box-shadow: none;
        outline: none;
    }
    
`);

/* ======================================================================= */

import CustomElement from "../../element/CustomElement.js";
import I18nLabel from "../../i18n/I18nLabel.js";
import UniqueEntriesStack from "../../../data/stack/UniqueEntriesStack.js";
import "../../symbols/CloseSymbol.js";

const Q_TAB = [
    "button:not([tabindex=\"-1\"])",
    "[href]:not([tabindex=\"-1\"])",
    "input:not([tabindex=\"-1\"])",
    "select:not([tabindex=\"-1\"])",
    "textarea:not([tabindex=\"-1\"])",
    "[tabindex]:not([tabindex=\"-1\"])"
].join(",");

const visibleModals = new UniqueEntriesStack();

export default class Window extends CustomElement {

    #titleEl;

    #closeEl;

    #focusTopEl;

    #focusBottomEl;

    constructor(title = "", close = "close") {
        super();
        this.shadowRoot.append(TPL.generate());
        STYLE.apply(this.shadowRoot);
        /* --- */
        this.addEventListener("keypress", (event) => {
            if (event.key == "Escape") {
                this.close();
            }
            event.stopPropagation();
        });
        this.#titleEl = this.shadowRoot.getElementById("title");
        this.#titleEl.append(I18nLabel.getLabel(title));
        this.#closeEl = this.shadowRoot.getElementById("close");
        if (!!close && typeof close === "string") {
            this.#closeEl.setAttribute("title", close);
        }
        this.#closeEl.addEventListener("click", () => this.close());
        /* --- */
        this.#focusTopEl = this.shadowRoot.getElementById("focus_catcher_top");
        this.#focusTopEl.addEventListener("focus", () => {
            this.focusLast();
        });
        this.#focusBottomEl = this.shadowRoot.getElementById("focus_catcher_bottom");
        this.#focusBottomEl.addEventListener("focus", () => {
            this.focusFirst();
        });
    }

    disconnectedCallback() {
        this.classList.remove("inactive");
    }

    show() {
        document.body.append(this);
        const oldModal = visibleModals.peek();
        if (oldModal != null) {
            oldModal.classList.add("inactive");
        }
        this.classList.remove("inactive");
        visibleModals.push(this);
        this.initialFocus();
    }

    remove() {
        super.remove();
        if (visibleModals.peek() === this) {
            visibleModals.pop();
            const lastModal = visibleModals.peek();
            if (lastModal != null) {
                lastModal.classList.remove("inactive");
            }
        } else {
            visibleModals.delete(this);
        }
    }

    close() {
        this.remove();
        this.dispatchEvent(new Event("close"));
    }

    #getAllFocusable() {
        const els = Array.from(this.shadowRoot.querySelectorAll(Q_TAB));
        return els.slice(1, -1);
    }

    #getBodyFocusable() {
        return Array.from(this.querySelectorAll(Q_TAB));
    }

    initialFocus() {
        const bodyEls = this.#getBodyFocusable();
        if (bodyEls.length) {
            bodyEls[0].focus();
        } else {
            const windowEls = this.#getAllFocusable();
            if (windowEls.length) {
                windowEls[0].focus();
            } else {
                this.#closeEl.focus();
            }
        }
    }

    focusFirst() {
        const windowEls = this.#getAllFocusable();
        if (windowEls.length) {
            windowEls[0].focus();
        } else {
            const bodyEls = this.#getBodyFocusable();
            if (bodyEls.length) {
                bodyEls[0].focus();
            } else {
                this.#closeEl.focus();
            }
        }
    }

    focusLast() {
        const windowEls = this.#getAllFocusable();
        if (windowEls.length) {
            windowEls[windowEls.length - 1].focus();
        } else {
            const bodyEls = this.#getBodyFocusable();
            if (bodyEls.length) {
                bodyEls[bodyEls.length - 1].focus();
            } else {
                this.#closeEl.focus();
            }
        }
    }

}

customElements.define("emc-window", Window);
