import { render } from "preact";
import styles from './style.module.css';
import { useCallback, useState } from "preact/hooks";
import { Command, commandInt16, NOTIFY_CHARACTERISTIC, PRINT_CHARACTERISTIC, PRINTER_SERVICE } from "./printer";

const Printer = () => {
    const [printer, setPrinter] = useState<BluetoothDevice>();
    const [service, setService] = useState<BluetoothRemoteGATTService>();
    const [characteristic, setCharacteristic] = useState<BluetoothRemoteGATTCharacteristic>();
    const [notifyCharacteristic, setNotifyCharacteristic] = useState<BluetoothRemoteGATTCharacteristic>();
    const [logs, setLogs] = useState('');

    const onConnect = useCallback(async () => {
        const device = await navigator.bluetooth.requestDevice({
            filters: [{ namePrefix: "MX" }],
            optionalServices: [PRINTER_SERVICE],
        });

        setPrinter(device);

        await device.gatt?.connect();
        const srv = await device.gatt?.getPrimaryService(PRINTER_SERVICE);

        setService(srv);

        const notify = await srv?.getCharacteristic(NOTIFY_CHARACTERISTIC);
        notify?.startNotifications();
        notify?.addEventListener('characteristicvaluechanged', (event) => {
            const value = notify?.value?.getUint8(6) ?? 0;
            setLogs(l => l + `\nNotify ${value}`);
        });

        setNotifyCharacteristic(notify);

        const writeChar = await srv?.getCharacteristic(PRINT_CHARACTERISTIC);
        setCharacteristic(writeChar);
    }, []);

    const onDisconnect = useCallback(async () => {
        printer?.gatt?.disconnect();
        setPrinter(undefined);
        setService(undefined);
        setCharacteristic(undefined);
    }, []);

    const onFeed = useCallback(async () => {
        if (characteristic) {
            await commandInt16(characteristic, Command.FeedPaper, 10);
        }
    }, [characteristic]);

    const onRetract = useCallback(async () => {
        if (characteristic) {
            await commandInt16(characteristic, Command.RetractPaper, 10);
        }
    }, [characteristic]);

    const onPrint = useCallback(async () => {
        if (characteristic) {
            // TODO
        }
    }, [characteristic, notifyCharacteristic]);

    return <div class={styles.printer}>
        <h2>Printer</h2>
        {printer
            ? <button onClick={onDisconnect}>Disconnect</button>
            : <button onClick={onConnect}>Connect</button>}
        <br />
        {characteristic && <>
            <button onClick={onRetract}>Retract</button><br />
            <button onClick={onFeed}>Feed</button><br />
            <button onClick={onPrint}>Print</button><br />
        </>}
        {printer && <pre>
            Connected to {printer.id}
            {service && `\nService: ${service.uuid}`}
            {characteristic && `\nChar: ${characteristic.uuid}`}
            {logs}
        </pre>}
    </div>;
};

export default function main() {
    const root = <Printer />;

    render(root, document.body);
}