import traceback
import httpx
from dacite import from_dict

from .models import DeviceModel, DeviceSettingsSetModel

HEATER_DISABLE_TEMP = -1000

class Device:
    model: DeviceModel
    _http_client: httpx.AsyncClient

    def __init__(self, http_client: httpx.Client, data: dict):
        self._http_client = http_client
        self.model = from_dict(data_class=DeviceModel, data=data)

    async def _set_params(self, params: DeviceSettingsSetModel):
        resp = await self._http_client.put(f"/devices/{self.model.id}/params", json=params.dict())
        resp.raise_for_status()
        device_info = resp.json()
        try:
            self.model = from_dict(data_class=DeviceModel, data = device_info)
        except Exception:
            print(traceback.format_exc())
            print(device_info)

    async def set_heat_temp(self, temp: int):
        if (temp < 100 or temp > 300) and temp != HEATER_DISABLE_TEMP:
            raise ValueError(f"set_heat_temp temp not between 100 and 300 and not -1000: {temp}")

        if temp % 10 not in [0, 5]:
            raise ValueError(f"set_heat_temp temp ends not with 0 or 5: {temp}")

        await self._set_params(DeviceSettingsSetModel(u_temp_room=temp))

    async def set_fan_speed(self, fan_speed: int):
        if fan_speed < 0 or fan_speed > 6:
            raise ValueError(f"set_fan_speed fan_speed not between 0 and 6: {fan_speed}")

        await self._set_params(DeviceSettingsSetModel(u_fan_speed=fan_speed))

    async def set_power_and_damp(self, power: bool, damp_pos: int):
        await self._set_params(DeviceSettingsSetModel(u_damp_pos=damp_pos, u_pwr_on=power))

    async def set_power_only(self, power: bool):
        """Set power without changing damper position."""
        await self._set_params(DeviceSettingsSetModel(u_pwr_on=power))

    async def set_damp_pos(self, damp_pos: int):
        """Set damper position: 0=open, 1=mixed, 2=closed"""
        if damp_pos not in [0, 1, 2]:
            raise ValueError(f"set_damp_pos damp_pos must be 0, 1 or 2: {damp_pos}")

        await self._set_params(DeviceSettingsSetModel(u_damp_pos=damp_pos))
