from .command import Command, CommandResult, CompositeCommand
from aamp_app.devices.dummy_heater import DummyHeater


class DummyHeaterParentCommand(Command):
    """Parent class for all DummyHeater commands."""

    receiver_cls = DummyHeater

    def __init__(self, receiver: DummyHeater, **kwargs):
        super().__init__(receiver, **kwargs)


class DummyHeaterInitialize(DummyHeaterParentCommand):
    """Initialize the heater by setting to room temp (25 C)."""

    def __init__(self, receiver: DummyHeater, **kwargs):
        super().__init__(receiver, **kwargs)

    def execute(self) -> None:
        self._result = CommandResult(*self._receiver.initialize())


class DummyHeaterDeinitialize(DummyHeaterParentCommand):
    """Deinitialize the heater by setting to room temp (25 C)."""

    def __init__(self, receiver: DummyHeater, reset_init_flag: bool = True, **kwargs):
        super().__init__(receiver, **kwargs)
        self._params["reset_init_flag"] = reset_init_flag

    def execute(self) -> None:
        self._result = CommandResult(
            *self._receiver.deinitialize(self._params["reset_init_flag"])
        )


class DummyHeaterSetHeatRate(DummyHeaterParentCommand):
    """Set the heating rate of the heater."""

    def __init__(self, receiver: DummyHeater, heat_rate: float, **kwargs):
        super().__init__(receiver, **kwargs)
        self._params["heat_rate"] = heat_rate

    def execute(self) -> None:
        self._receiver.heat_rate = self._params["heat_rate"]

        # logic implemented here because heat_rate setter does not return Tuple[bool, str]
        if self._receiver.heat_rate == self._params["heat_rate"]:
            self._result = CommandResult(
                True,
                "Successfully set DummyHeater heat rate to "
                + str(self._receiver.heat_rate),
            )
        else:
            self._result = CommandResult(
                False,
                "Failed to set DummyHeater heat rate. Heat rate is currently "
                + str(self._receiver.heat_rate),
            )


class DummyHeaterSetTemp(DummyHeaterParentCommand):
    """Set the temperature of the heater and wait for it to stabilize."""

    def __init__(self, receiver: DummyHeater, temperature: float, **kwargs):
        super().__init__(receiver, **kwargs)
        self._params["temperature"] = temperature

    def execute(self) -> None:
        self._result = CommandResult(
            *self._receiver.set_temp(self._params["temperature"])
        )


# Composite command example
class DummyHeaterRampHoldRamp(CompositeCommand):
    """Ramps up to temperature1 @ rate1, holds for specified time, then ramps to temperature2 @ rate2"""

    def __init__(
        self,
        receiver: DummyHeater,
        temp1: float,
        rate1: float,
        hold_time: float,
        temp2: float,
        rate2: float,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.add_command(DummyHeaterSetHeatRate(receiver, rate1))
        self.add_command(DummyHeaterSetTemp(receiver, temp1))
        self.add_command(DummyHeaterSetHeatRate(receiver, rate2, delay=hold_time))
        self.add_command(DummyHeaterSetTemp(receiver, temp2))
