import MuiSlider from "@mui/material/Slider";
import React from "react";
import { useState, useEffect, useRef } from "react";

type StateItem = {
    value: number,
    status: "open" | "owned" | "locked",
};

type State = Array<StateItem>;

type ClientAction = {
    action_type: "grab" | "release",
    slider: number,
} | {
    action_type: "move",
    slider: number,
    new_value: number,
}

const Sliders: React.FC = () => {
    const ws = useRef<WebSocket>();
    const reconnectInterval = useRef<number>();

    const [state, setState] = useState<State>();

    const connect = () => {
        // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
        if (ws.current !== undefined && ws.current.readyState !== 3) return;

        const wsURL = new URL("ws", window.location.href);
        wsURL.protocol = wsURL.protocol.replace("http", "ws");
        ws.current = new WebSocket(wsURL.href);

        ws.current.onmessage = (ev) => {
            setState(JSON.parse(ev.data));
        }

    }

    useEffect(() => {
        connect();
        reconnectInterval.current = window.setInterval(connect, 1000);

        return () => {
            if (reconnectInterval.current !== undefined) window.clearInterval(reconnectInterval.current);
            if (ws.current !== undefined) ws.current.close();
        };
    }, []);

    const cb = (action: ClientAction) => {
        if (ws.current !== undefined && ws.current.readyState !== 3) {
            ws.current.send(JSON.stringify({
                action: action,
            }));
        }
    }

    return <>
        {state?.map((item, index) => <Slider key={index} item={item} index={index} cb={cb} />)}
    </>
}


const styleOverride = {
    "& .MuiSlider-track": { transition: "none" },
    "& .MuiSlider-thumb": { transition: "none" },
};

const Slider: React.FC<{
    item: StateItem,
    index: number,
    cb: (action: ClientAction) => void,
}> = ({ item, index, cb }) => {

    const disabled = item.status === "locked";
    const [value, setValue] = useState(item.value);

    useEffect(() => {
        if (item.status !== "owned") setValue(item.value);
    }, [item]);

    const onChange = (n: number) => {
        setValue(n);
        cb({
            action_type: "move",
            slider: index,
            new_value: n,
        });
    };

    const onGrab = () => {
        cb({
            action_type: "grab",
            slider: index,
        });
    };

    const onRelease = () => {
        cb({
            action_type: "release",
            slider: index,
        });
    };

    return <MuiSlider
        min={0}
        max={255}
        sx={disabled ? styleOverride : {}}
        disabled={disabled}
        value={value}
        onChange={(_, n) => { onChange(n as number) }}
        onMouseDown={onGrab}
        onTouchStart={onGrab}
        onMouseUp={onRelease}
        onTouchEnd={onRelease}
    />
};

export default Sliders;