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

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

const TPL = new Template(`
    <div id="container">
        <div id="close">✖</div>
        <slot id="map"></slot>
    </div>
    
`);

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

const STYLE = new GlobalStyle(`
    :host {
        position: absolute;
        display: none;
        align-items: center;
        justify-content: center;
        top: 0px;
        bottom: 0px;
        left: 0px;
        right: 0px;
        overflow: hidden;
        user-select: none;
        backdrop-filter: blur(2px);
    }
    
    :host(.show) {
        display: flex;
    }
    
    #container {
        position: relative;
        display: flex;
        align-items: flex-end;
        justify-content: center;
        flex-direction: column;
        background-color: var(--navigation-back-color, #ffffff);
        border-style: solid;
        border-width: 2px;
        border-color: var(--page-border-color-inverted, #ffffff);
    }
    
    #map {
        position: relative;
        display: block;
        width: 100px;
        height: 100px;
        flex-shrink: 0;
        background-color: var(--page-text-color, #000000);
        background-repeat: no-repeat;
        background-size: 100%;
        background-position: center;
        background-origin: content-box;
    }
    
    ::slotted(*) {
        position: absolute;
    }
    
    #close {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 32px;
        height: 32px;
        color: var(--modal-close-text-color, #222222);
        background-color: var(--modal-close-back-color, #ffb9b9);
        background-image: var(--modal-close-back-image, none);
        font-size: 1.4em;
        cursor: pointer;
    }
    
    #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);
    }
    
`);

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

import CustomElement from "/emcJS/ui/element/CustomElement.js";
import {
    mix
} from "/emcJS/util/Mixin.js";
import ElementManager from "/emcJS/util/html/ElementManager.js";
import "/emcJS/ui/i18n/I18nLabel.js";
import SettingsObserver from "../../../../../util/observer/SettingsObserver.js";
import WorldStateManagerRegistry from "../../../../../statemanager/WorldStateManagerRegistry.js";
import WorldListState from "../../../../../state/world/WorldListState.js";
import UIRegistry from "../../../../../registry/UIRegistry.js";
import StateDataEventManagerMixin from "../../../../mixin/StateDataEventManagerMixin.js";
import "../entries/Location.js";
import "../entries/Area.js";
import "../entries/Exit.js";

const showMapConnectionsObserver = new SettingsObserver("show_map_connections");

class MapMarkerElementManager extends ElementManager {

    composer(key, params) {
        if (params.type === "connection") {
            return document.createElement("gt-connection");
        }
        const uiReg = UIRegistry.get(`worldmap-${params.type.toLowerCase()}`);
        if (uiReg != null) {
            return uiReg.create(params.subtype, key);
        }
    }

    mutator(el, key, params) {
        if (params.type === "connection") {
            el.innerHTML = "";
            for (const position of params.coordinates) {
                const {x, y} = position ?? {};
                if (!isNaN(x) && !isNaN(y)) {
                    const connectionPointEl = document.createElement("gt-connection-point");
                    connectionPointEl.label = params.label;
                    connectionPointEl.left = position.x;
                    connectionPointEl.top = position.y;
                    connectionPointEl.scale = position.scale;
                    el.append(connectionPointEl);
                }
            }
        } else {
            el.left = params.x;
            el.top = params.y;
            el.scale = params.scale;
            // XXX tooltips should really automatically adjust
            el.tooltip = calculateTooltipPosition(params.x, params.y, params.areaWidth, params.areaHeight);
        }
    }

}

const ZOOM_MIN = 10;
const ZOOM_MAX = 200;

const BaseClass = mix(
    CustomElement
).with(
    StateDataEventManagerMixin
);

export default class WorldMapMetaAreaView extends BaseClass {

    #elementManager;

    #mapEl;

    #closeEl;

    constructor() {
        super();
        this.shadowRoot.append(TPL.generate());
        STYLE.apply(this.shadowRoot);
        /* --- */
        this.#mapEl = this.shadowRoot.getElementById("map");
        this.#closeEl = this.shadowRoot.getElementById("close");
        this.#closeEl.addEventListener("click", () => {
            this.hide();
        });
        this.addEventListener("wheel", (event) => {
            event.stopPropagation();
            event.preventDefault();
        });

        /* state handler */
        WorldListState.addEventListener("area", () => {
            this.hide();
        });
        this.registerStateHandler("listChange", () => {
            this.refreshList();
        });

        /* settings */
        showMapConnectionsObserver.onChange(() => {
            this.refreshList();
        });

        /* --- */
        this.#elementManager = new MapMarkerElementManager(this.#mapEl);

        /* --- */
        const {ref} = WorldListState.config.metaArea;
        const state = WorldStateManagerRegistry.get(ref?.type)?.get(ref?.name);
        this.switchState(state);
    }

    applyDefaultValues() {
        /* map */
        this.#mapEl.style.backgroundColor = "#000000";
        this.#mapEl.style.backgroundImage = "";
        this.#mapEl.style.width = "600px";
        this.#mapEl.style.height = "600px";
        /* zoom */
        this.#mapEl.style.setProperty("--zoom", 100);
        /* list */
        this.refreshList();
    }

    applyStateValues(state) {
        /* map */
        const mapData = state.props.map;
        this.#mapEl.style.backgroundColor = mapData.backgroundColor;
        this.#mapEl.style.backgroundImage = `url("${mapData.backgroundImage}")`;
        this.#mapEl.style.width = `${mapData.width}px`;
        this.#mapEl.style.height = `${mapData.height}px`;
        /* zoom */
        const zoom = mapData.zoom ?? 100;
        const resultZoom = Math.min(Math.max(ZOOM_MIN, Math.floor(zoom ?? 100)), ZOOM_MAX);
        this.#mapEl.style.setProperty("--zoom", resultZoom);
        /* list */
        this.refreshList();
    }

    refreshList() {
        const elManagerData = [];
        const state = this.getState();
        if (state != null) {
            const list = state.getList();
            if (list != null && list.length > 0) {
                for (const record of list) {
                    if (!isNaN(record.x) && !isNaN(record.y)) {
                        const loc = record.entry;
                        elManagerData.push({
                            key: loc.ref,
                            type: record.type,
                            subtype: loc.props.type,
                            x: record.x,
                            y: record.y,
                            scale: record.scale,
                            areaWidth: state.props.map.width,
                            areaHeight: state.props.map.height
                        });
                    }
                }
            }
            if (showMapConnectionsObserver.value) {
                const connections = state.props.connections;
                if (connections != null) {
                    for (const connection of connections) {
                        elManagerData.push({
                            key: `connection___${connection.label}`,
                            label: connection.label,
                            type: "connection",
                            coordinates: [
                                connection.posA,
                                connection.posB
                            ]
                        });
                    }
                }
            }
        }
        this.#elementManager.manage(elManagerData);
    }

    show() {
        this.classList.add("show");
    }

    hide() {
        this.classList.remove("show");
    }

}

customElements.define("gt-worldmap-metaarea-view", WorldMapMetaAreaView);

function calculateTooltipPosition(posX, posY, mapW, mapH) {
    const leftP = posX / mapW;
    const topP = posY / mapH;
    let tooltip = "";
    if (topP < 0.3) {
        tooltip = "bottom";
    } else if (topP > 0.7) {
        tooltip = "top";
    }
    if (leftP < 0.3) {
        tooltip += "right";
    } else if (leftP > 0.7) {
        tooltip += "left";
    }
    return tooltip || "top";
}
