import logging

from nicegui import ui

logger = logging.getLogger("xmas_app")


async def initialize_qwebchannel() -> None:
    """Initializes a reusable `QWebChannel` including a handler."""
    success, error = await ui.run_javascript(
        """
            return (function () {
                if (window.ensureXmasHandler) {
                    return [true, null];
                }

                if (!window.qt || !window.QWebChannel || !qt.webChannelTransport) {
                    return [false, 'Qt objects missing'];
                }

                window.ensureXmasHandler = async function ensureXmasHandler() {
                    if (window.xmasHandler) {
                        return window.xmasHandler;
                    }

                    return await new Promise((resolve, reject) => {
                        new QWebChannel(qt.webChannelTransport, function (channel) {
                            window.xmasChannel = channel;
                            window.xmasHandler = channel.objects.handler;
                            resolve(window.xmasHandler);
                        });
                    });
                };
                return [true, null];
            })();
        """
    )
    if not success:
        logger.error("failed to initialize QWebChannel: %s", error)
        ui.notify("Kommunikation mit QGIS nicht möglich", type="negative")


async def connect_signal(signal_name: str) -> None:
    """Connects NiceGUI's `emitEvent` function to a `QWebChannel` handler signal."""
    success, error = await ui.run_javascript(
        f"""
            return (async function () {{
                if (!window.ensureXmasHandler) {{
                    return [false, 'ensureXmasHandler missing'];
                }}

                const handler = window.xmasHandler || await window.ensureXmasHandler().catch(err => {{
                    return [false, err];
                }});

                const callback = handler.{signal_name}Callback || (handler.{signal_name}Callback = (data) => emitEvent('{signal_name}', data));
                try {{
                    handler.{signal_name}.disconnect(callback);
                }} catch (err) {{
                    // handler may not have been connected yet
                }}
                handler.{signal_name}.connect(callback);
                return [true, null];
            }})();
        """
    )
    if not success:
        ui.notify(f"Verbindung zu Signal {signal_name} fehlgeschlagen", type="negative")
        logger.error(
            "failed to bind %r signal to QWebChannel handler: %s",
            signal_name,
            error,
        )
