function bufferToHex(buffer) {
    return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, '0')).join('');
}

class PacketSource {
    constructor(pyodide) {
        this.parser = pyodide.runPython(`
            from bumble.transport.common import PacketParser
            class ProxiedPacketParser(PacketParser):
                def feed_data(self, js_data):
                    super().feed_data(bytes(js_data.to_py()))
            ProxiedPacketParser()
      `);
    }

    set_packet_sink(sink) {
        this.parser.set_packet_sink(sink);
    }

    data_received(data) {
        //console.log(`HCI[controller->host]: ${bufferToHex(data)}`);
        this.parser.feed_data(data);
    }
}

class PacketSink {
    constructor() {
        this.queue = [];
        this.isProcessing = false;
    }

    on_packet(packet) {
        if (!this.writer) {
            return;
        }
        const buffer = packet.toJs({create_proxies : false});
        packet.destroy();
        //console.log(`HCI[host->controller]: ${bufferToHex(buffer)}`);
        this.queue.push(buffer);
        this.processQueue();
    }

    async processQueue() {
        if (this.isProcessing) {
            return;
        }
        this.isProcessing = true;
        while (this.queue.length > 0) {
            const buffer = this.queue.shift();
            await this.writer(buffer);
        }
        this.isProcessing = false;
    }
}


class LogEvent extends Event {
    constructor(message) {
        super('log');
        this.message = message;
    }
}

export class Bumble extends EventTarget {
    constructor(pyodide) {
        super();
        this.pyodide = pyodide;
    }

    async loadRuntime(bumblePackage) {
        // Load pyodide if it isn't provided.
        if (this.pyodide === undefined) {
            this.log('Loading Pyodide');
            this.pyodide = await loadPyodide();
        }

        // Load the Bumble module
        console.log('Installing micropip');
        this.log(`Installing ${bumblePackage}`)
        await this.pyodide.loadPackage('micropip');
        await this.pyodide.runPythonAsync(`
            import micropip
            await micropip.install('${bumblePackage}')
            package_list = micropip.list()
            print(package_list)
        `)

        // Mount a filesystem so that we can persist data like the Key Store
        let mountDir = '/bumble';
        this.pyodide.FS.mkdir(mountDir);
        this.pyodide.FS.mount(this.pyodide.FS.filesystems.IDBFS, { root: '.' }, mountDir);

        // Sync previously persisted filesystem data into memory
        await new Promise(resolve => {
            this.pyodide.FS.syncfs(true, () => {
                console.log('FS synced in');
                resolve();
            });
        })

        // Setup the HCI source and sink
        this.packetSource = new PacketSource(this.pyodide);
        this.packetSink = new PacketSink();
    }

    log(message) {
        this.dispatchEvent(new LogEvent(message));
    }

    async connectWebSocketTransport(hciWsUrl) {
        return new Promise((resolve, reject) => {
            let resolved = false;

            let ws = new WebSocket(hciWsUrl);
            ws.binaryType = 'arraybuffer';

            ws.onopen = () => {
                this.log('WebSocket open');
                resolve();
                resolved = true;
            }

            ws.onclose = () => {
                this.log('WebSocket close');
                if (!resolved) {
                    reject(`Failed to connect to ${hciWsUrl}`);
                }
            }

            ws.onmessage = (event) => {
                this.packetSource.data_received(event.data);
            }

            this.packetSink.writer = (packet) => {
                if (ws.readyState === WebSocket.OPEN) {
                    ws.send(packet);
                }
            }
            this.closeTransport = async () => {
                if (ws.readyState === WebSocket.OPEN) {
                    ws.close();
                }
            }
        })
    }

    async loadApp(appUrl) {
        this.log('Loading app');
        const script = await (await fetch(appUrl)).text();
        await this.pyodide.runPythonAsync(script);
        const pythonMain = this.pyodide.globals.get('main');
        const app = await pythonMain(this.packetSource, this.packetSink);
        if (app.on) {
            app.on('key_store_update', this.onKeystoreUpdate.bind(this));
        }
        this.log('App is ready!');
        return app;
    }

    onKeystoreUpdate() {
        // Sync the FS
        this.pyodide.FS.syncfs(() => {
            console.log('FS synced out');
        });
    }
}

async function getBumblePackage() {
    const params = (new URL(document.location)).searchParams;
    // First check the packageFile override param
    if (params.has('packageFile')) {
        return await (await fetch('/packageFile')).text() 
    }
    // Then check the package override param
    if (params.has('package')) {
        return params.get('package')
    }
    // If no override params, default to the main package
    return 'bumble'
}

export async function setupSimpleApp(appUrl, bumbleControls, log) {
    // Load Bumble
    log('Loading Bumble');
    const bumble = new Bumble();
    bumble.addEventListener('log', (event) => {
        log(event.message);
    })
    await bumble.loadRuntime(await getBumblePackage());

    log('Bumble is ready!')
    const app = await bumble.loadApp(appUrl);

    bumbleControls.connector = async (hciWsUrl) => {
        try {
            // Connect the WebSocket HCI transport
            await bumble.connectWebSocketTransport(hciWsUrl);

            // Start the app
            await app.start();

            return true;
        } catch (err) {
            log(err);
            return false;
        }
    }
    bumbleControls.stopper = async () => {
        // Stop the app
        await app.stop();

        // Close the HCI transport
        await bumble.closeTransport();
    }
    bumbleControls.onBumbleLoaded();

    return app;
}
