from __future__ import annotations

from dataclasses import dataclass

from matterlab_serial_device import ScriptedSerialTransport
from matterlab_serial_device.transport import SerialTransportConfig


@dataclass
class IKARV10SimState:
    name: str = "RV10"
    software_version: str = "1.0.0"
    current_rpm: int = 0
    target_rpm: int = 0
    interval: int = 0
    timer: int = 0
    rotating: bool = False
    lift_state: str = "stopped"


class IKARV10SimProtocol:
    def __init__(self, state: IKARV10SimState) -> None:
        self.state = state

    def __call__(self, write_data: bytes, expected: bytes, size: int | None) -> bytes:
        del expected, size
        command = write_data.decode("utf-8").strip()

        if command == "IN_NAME":
            return f"IN_NAME {self.state.name}\r\n".encode("utf-8")
        if command == "IN_SOFTWARE":
            return f"IN_SOFTWARE {self.state.software_version}\r\n".encode("utf-8")
        if command == "IN_PV_4":
            return f"IN_PV_4 {self.state.current_rpm}\r\n".encode("utf-8")
        if command == "IN_SP_4":
            return f"IN_SP_4 {self.state.target_rpm}\r\n".encode("utf-8")
        if command.startswith("OUT_SP_4 "):
            self.state.target_rpm = int(command.split()[1])
            return f"{command}\r\n".encode("utf-8")
        if command == "START_4":
            self.state.rotating = True
            self.state.current_rpm = self.state.target_rpm
            return b"START_4 OK\r\n"
        if command == "STOP_4":
            self.state.rotating = False
            self.state.current_rpm = 0
            self.state.target_rpm = 0
            return b"STOP_4 OK\r\n"
        if command.startswith("OUT_SP_60 "):
            self.state.interval = int(command.split()[1])
            return f"{command}\r\n".encode("utf-8")
        if command.startswith("OUT_SP_61 "):
            self.state.timer = int(command.split()[1])
            return f"{command}\r\n".encode("utf-8")
        if command == "OUT_SP_62 1":
            self.state.lift_state = "up"
            return b"OUT_SP_62 1\r\n"
        if command == "START_62":
            self.state.lift_state = "down"
            return b"START_62 OK\r\n"
        if command == "STOP_62":
            self.state.lift_state = "stopped"
            return b"STOP_62 OK\r\n"
        if command == "RESET":
            self.state.current_rpm = 0
            self.state.target_rpm = 0
            self.state.rotating = False
            self.state.interval = 0
            self.state.timer = 0
            self.state.lift_state = "stopped"
            return b"RESET OK\r\n"
        return b"OK 1\r\n"


def create_ika_rotavap_sim_transport_factory(
    *,
    name: str = "RV10",
    software_version: str = "1.0.0",
    current_rpm: int = 0,
    target_rpm: int = 0,
    interval: int = 0,
    timer: int = 0,
):
    state = IKARV10SimState(
        name=name,
        software_version=software_version,
        current_rpm=current_rpm,
        target_rpm=target_rpm,
        interval=interval,
        timer=timer,
    )
    protocol = IKARV10SimProtocol(state)

    def _factory(config: SerialTransportConfig):
        return ScriptedSerialTransport(config, default_response=protocol)

    _factory.state = state
    return _factory
