import { getParam } from "../engine_utils.js";
import { getErrorCount } from "./debug_overlay.js";

let consoleInstance: VConsole | null | undefined = undefined;
let consoleHtmlElement: HTMLElement | null = null;
let consoleSwitchButton: HTMLElement | null = null;
let isLoading = false;
let isVisible = false;
let watchInterval: any = null;
const defaultButtonIcon = "terminal";

const showConsole = getParam("console");
if (showConsole) {
    showDebugConsole();
}

const $defaultConsoleParent = Symbol("consoleParent");

export function showDebugConsole() {

    if (consoleInstance) {
        isVisible = true;
        consoleInstance.showSwitch();
        return;
    }
    createConsole();
}

export function hideDebugConsole() {
    if (!consoleInstance) return;
    isVisible = false;
    consoleInstance.hide();
    consoleInstance.hideSwitch();
}

function beginWatchingLogs() {
    if (watchInterval) return;
    watchInterval = setInterval(consoleElementUpdateInterval, 500);
}

let lastErrorCount = 0;
function consoleElementUpdateInterval() {
    const currentCount = getErrorCount();
    const receivedNewErrors = currentCount !== lastErrorCount;
    lastErrorCount = currentCount;
    if (receivedNewErrors) {
        onNewConsoleErrors();
    }
}

function onNewConsoleErrors() {
    showDebugConsole();
    if (consoleSwitchButton) {
        consoleSwitchButton.setAttribute("error", "true");
        consoleSwitchButton.innerText = "🤬"
    }
}

function onConsoleSwitchButtonClicked() {
    if (consoleSwitchButton) {
        consoleSwitchButton.removeAttribute("error");
        consoleSwitchButton.innerText = defaultButtonIcon;
    }
}

function onResetConsoleElementToDefaultParent() {
    if (consoleHtmlElement && consoleHtmlElement[$defaultConsoleParent]) {
        consoleHtmlElement[$defaultConsoleParent].appendChild(consoleHtmlElement);
    }
}

declare class VConsole {
    addPlugin: (plugin: any) => void;
    setSwitchPosition: (x: number, y: number) => void;
    show: () => void;
    hide: () => void;
    hideSwitch: () => void;
    showSwitch: () => void;
    constructor(options: {
        defaultPlugins?: string[],
        pluginOrder?: string[],
    });
    static VConsolePlugin: any;
}

declare class PluginBtn {
    name: string;
    className?: string;
    data?: any;
    onClick: (event: Event, data: {type: string}) => void;
}

function createConsole(startHidden: boolean = false) {
    if (consoleInstance !== undefined) return;
    if (isLoading) return;
    isLoading = true;

    const script = document.createElement("script");
    script.onload = () => {
        // check if VConsole is now defined on globalThis
        if (!globalThis.VConsole) {
            console.warn("🌵 Debug console failed to load."); 
            isLoading = false;
            consoleInstance = null;
            return;
        }
        isLoading = false;
        isVisible = true;
        beginWatchingLogs();
        consoleInstance = new VConsole({
            // defaultPlugins: ['system', 'network'],
            pluginOrder: ['default', 'needle-console'],
        }) as VConsole;
        
        const files = globalThis["needle:codegen_files"];
        if (files && files.length > 0) {
            consoleInstance.addPlugin(createInspectPlugin());
        }

        consoleHtmlElement = getConsoleElement();
        if (consoleHtmlElement) {
            consoleHtmlElement[$defaultConsoleParent] = consoleHtmlElement.parentElement;
            consoleHtmlElement.style.position = "absolute";
            consoleHtmlElement.style.zIndex = Number.MAX_SAFE_INTEGER.toString();
            // const styleSheetList = document.styleSheets;
            // for (let i = 0; i < styleSheetList.length; i++) {
            //     const styleSheet = styleSheetList[i];
            //     const firstRule = styleSheet.cssRules[0] as CSSStyleRule;
            //     if(firstRule && firstRule.selectorText === "#__vconsole") {
            //         console.log("found vconsole style sheet");
            //         const styleTag = document.createElement("style");
            //         styleTag.innerHTML = "#__needleconsole {}";
            //         for (let j = 0; j < styleSheet.cssRules.length; j++) {
            //             const rule = styleSheet.cssRules[j] as CSSStyleRule;
            //             styleTag.innerHTML += rule.cssText;
            //         }
            //         consoleHtmlElement.appendChild(styleTag);
            //     }
            // }
        }
        consoleInstance.setSwitchPosition(20, 30);
        consoleSwitchButton = getConsoleSwitchButton();
        if (consoleSwitchButton) {
            consoleSwitchButton.innerText = defaultButtonIcon;
            consoleSwitchButton.addEventListener("click", onConsoleSwitchButtonClicked);
            const styles = document.createElement("style");
            const size = 40;
            styles.innerHTML = `
                #__vconsole .vc-switch {
                    border: 1px solid rgba(255, 255, 255, .1);
                    border-radius: 50%;
                    width: ${size}px;
                    height: ${size}px;
                    padding: 0;
                    line-height: ${size}px;
                    font-size: ${size * .4}px;
                    text-align: center;
                    background: #ffffff5c;
                    backdrop-filter: blur(16px);
                    -webkit-backdrop-filter: blur(16px);
                    user-select: none;
                    pointer-events: auto;
                    transition: transform .2s ease-in-out;
                    box-shadow: 0px 7px 0.5rem 0px rgb(0 0 0 / 6%), inset 0px 0px 1.3rem rgba(0,0,0,.05);

                    font-family: 'Material Symbols Outlined';
                    color: black;
                    font-size: 2.3em;
                    font-weight: 100;
                }
                #__vconsole .vc-switch:hover {
                    cursor: pointer;
                    transform: scale(1.1);
                    transition: transform .1s ease-in-out, background .1s linear;
                    background: rgba(245, 245, 245, .8);
                    outline: rgba(0, 0, 0, .05) 1px solid;
                }
                #__vconsole .vc-switch[error] {
                    background: rgba(255,0,0,.2);
                    animation: vconsole-notify 1s ease-in-out;
                    line-height: 35px;
                }
                @keyframes vconsole-notify {
                    from {
                        transform: scale(1, 1);
                    }
                    10% {
                        transform: scale(1.3, 1.3);
                    }
                    70% {
                        transform: scale(1.4, 1.4);
                    }
                    to {
                        transform: scale(1, 1);
                    }
                }
                #__vconsole .vc-panel {
                    font-family: monospace;
                    font-size: 11px;
                }
                #__vconsole .vc-plugin-box.vc-actived {
                    height: 100%;
                }
                #__vconsole .vc-mask {
                    overflow: hidden;
                }
            `;
            consoleHtmlElement?.prepend(styles);
            if (startHidden === true && getErrorCount() <= 0)
                hideDebugConsole();
            console.log("🌵 Debug console has loaded");
        }

    };
    script.onerror = () => {
        console.warn("🌵 Debug console failed to load." + (window.crossOriginIsolated ? "This page is using cross-origin isolation, so external scripts can't be loaded." : ""));
        isLoading = false;
        consoleInstance = null;
    };
    script.src = "https://cdn.jsdelivr.net/npm/vconsole@3.15.1/dist/vconsole.min.js";
    document.body.appendChild(script);
}

function createInspectPlugin() {
    if (!globalThis.VConsole) return;
    const plugin = new VConsole.VConsolePlugin("needle-console", "🌵 Inspect glTF");
    const getIframe = () => {
        return document.querySelector("#__vc_plug_" + plugin._id + " iframe") as HTMLIFrameElement;
    }
    plugin.on('renderTab', function(callback) {
        const files = globalThis["needle:codegen_files"];
        if (!files || files.length === 0) return;
        let query = globalThis["needle:codegen_files"][0];
        const index = query.indexOf("?");
        if (index > -1) query = query.substring(0, index);
        const currentAbsolutePath = location.protocol + '//' + location.host + location.pathname;
        const currentPath = currentAbsolutePath + "/" + query;
        const urlEncoded = encodeURIComponent(currentPath);
        plugin.fullUrl = "https://viewer.needle.tools?inspect&file=" + urlEncoded;
        var html = `<iframe src="" style="width: 100%; height: 99%; border: none;"></iframe>`;
        callback(html);
    });
    plugin.on('show', function() {
        const elem = getIframe();
        if (elem && elem.src !== plugin.fullUrl) elem.src = plugin.fullUrl;
    });
    plugin.on('hide', function() {
        const elem = getIframe();
        if (elem) elem.src = "";
    });
    /* bottom tool bar
    plugin.on('addTool', function(callback) {
        var button = {
            name: 'Reload',
            onClick: function(event) {
                location.reload();
            }
        };
        callback([button]);
    });
    */
    plugin.on('addTopBar', function(callback) {
        var btnList = new Array<PluginBtn>();
        btnList.push({
            name: 'Open in new window ↗',
            onClick: function(_event) {
                window.open(plugin.fullUrl, '_blank');
                consoleInstance?.hide();
            }
        });
        btnList.push({
            name: 'Reload',
            onClick: function(_event) {
                const iframe = getIframe();
                if (iframe) iframe.src = plugin.fullUrl;
            }
        });
        btnList.push({
            name: 'Fullscreen',
            onClick: function(_event) {
                const iframe = getIframe();
                if (iframe.requestFullscreen) {
                    iframe.requestFullscreen();
                } else if (iframe["webkitRequestFullscreen"] instanceof Function) {
                    iframe["webkitRequestFullscreen"]();
                }
            }
        });
        callback(btnList);
    });
    return plugin;
}

function getConsoleSwitchButton(): HTMLElement | null {
    const el = document.querySelector("#__vconsole .vc-switch");
    if (el) return el as HTMLElement;
    return null;
}

function getConsoleElement(): HTMLElement | null {
    const el = document.querySelector("#__vconsole");
    if (el) return el as HTMLElement;
    return null;
}