"""Auto-generated LIFX protocol types.

DO NOT EDIT THIS FILE MANUALLY.
Generated from https://github.com/LIFX/public-protocol/blob/main/protocol.yml
by protocol/generator.py

Uses Pythonic naming conventions (snake_case fields, shortened enums) while
maintaining compatibility with the official LIFX protocol through mappings.
"""

from __future__ import annotations

from dataclasses import dataclass
from enum import IntEnum


class DeviceService(IntEnum):
    """Auto-generated enum."""

    UDP = 1


class Direction(IntEnum):
    """Auto-generated enum."""

    REVERSED = 0
    FORWARD = 1


class FirmwareEffect(IntEnum):
    """Auto-generated enum."""

    OFF = 0
    MOVE = 1
    MORPH = 2
    FLAME = 3
    SKY = 5


class LightLastHevCycleResult(IntEnum):
    """Auto-generated enum."""

    SUCCESS = 0
    BUSY = 1
    INTERRUPTED_BY_RESET = 2
    INTERRUPTED_BY_HOMEKIT = 3
    INTERRUPTED_BY_LAN = 4
    INTERRUPTED_BY_CLOUD = 5
    NONE = 255


class LightWaveform(IntEnum):
    """Auto-generated enum."""

    SAW = 0
    SINE = 1
    HALF_SINE = 2
    TRIANGLE = 3
    PULSE = 4


class MultiZoneApplicationRequest(IntEnum):
    """Auto-generated enum."""

    NO_APPLY = 0
    APPLY = 1
    APPLY_ONLY = 2


class TileEffectSkyPalette(IntEnum):
    """Auto-generated enum."""

    CLOUDS_SKY = 0
    NIGHT_SKY = 1
    DAWN_SKY = 2
    DAWN_SUN = 3
    FULL_SUN = 4
    FINAL_SUN = 5
    NUM_COLOURS = 6


class TileEffectSkyType(IntEnum):
    """Auto-generated enum."""

    SUNRISE = 0
    SUNSET = 1
    CLOUDS = 2


@dataclass
class DeviceStateHostFirmware:
    """Auto-generated field structure."""

    build: int
    version_minor: int
    version_major: int

    def pack(self) -> bytes:
        """Pack to bytes."""
        from lifx.protocol import serializer

        result = b""

        # build: uint64
        result += serializer.pack_value(self.build, "uint64")
        # Reserved 8 bytes
        result += serializer.pack_reserved(8)
        # version_minor: uint16
        result += serializer.pack_value(self.version_minor, "uint16")
        # version_major: uint16
        result += serializer.pack_value(self.version_major, "uint16")

        return result

    @classmethod
    def unpack(
        cls, data: bytes, offset: int = 0
    ) -> tuple[DeviceStateHostFirmware, int]:
        """Unpack from bytes."""
        from lifx.protocol import serializer

        current_offset = offset
        # build: uint64
        build, current_offset = serializer.unpack_value(data, "uint64", current_offset)
        # Skip reserved 8 bytes
        current_offset += 8
        # version_minor: uint16
        version_minor, current_offset = serializer.unpack_value(
            data, "uint16", current_offset
        )
        # version_major: uint16
        version_major, current_offset = serializer.unpack_value(
            data, "uint16", current_offset
        )

        return cls(
            build=build, version_minor=version_minor, version_major=version_major
        ), current_offset


@dataclass
class DeviceStateVersion:
    """Auto-generated field structure."""

    vendor: int
    product: int

    def pack(self) -> bytes:
        """Pack to bytes."""
        from lifx.protocol import serializer

        result = b""

        # vendor: uint32
        result += serializer.pack_value(self.vendor, "uint32")
        # product: uint32
        result += serializer.pack_value(self.product, "uint32")
        # Reserved 4 bytes
        result += serializer.pack_reserved(4)

        return result

    @classmethod
    def unpack(cls, data: bytes, offset: int = 0) -> tuple[DeviceStateVersion, int]:
        """Unpack from bytes."""
        from lifx.protocol import serializer

        current_offset = offset
        # vendor: uint32
        vendor, current_offset = serializer.unpack_value(data, "uint32", current_offset)
        # product: uint32
        product, current_offset = serializer.unpack_value(
            data, "uint32", current_offset
        )
        # Skip reserved 4 bytes
        current_offset += 4

        return cls(vendor=vendor, product=product), current_offset


@dataclass
class LightHsbk:
    """Auto-generated field structure."""

    hue: int
    saturation: int
    brightness: int
    kelvin: int

    def pack(self) -> bytes:
        """Pack to bytes."""
        from lifx.protocol import serializer

        result = b""

        # hue: uint16
        result += serializer.pack_value(self.hue, "uint16")
        # saturation: uint16
        result += serializer.pack_value(self.saturation, "uint16")
        # brightness: uint16
        result += serializer.pack_value(self.brightness, "uint16")
        # kelvin: uint16
        result += serializer.pack_value(self.kelvin, "uint16")

        return result

    @classmethod
    def unpack(cls, data: bytes, offset: int = 0) -> tuple[LightHsbk, int]:
        """Unpack from bytes."""
        from lifx.protocol import serializer

        current_offset = offset
        # hue: uint16
        hue, current_offset = serializer.unpack_value(data, "uint16", current_offset)
        # saturation: uint16
        saturation, current_offset = serializer.unpack_value(
            data, "uint16", current_offset
        )
        # brightness: uint16
        brightness, current_offset = serializer.unpack_value(
            data, "uint16", current_offset
        )
        # kelvin: uint16
        kelvin, current_offset = serializer.unpack_value(data, "uint16", current_offset)

        return cls(
            hue=hue, saturation=saturation, brightness=brightness, kelvin=kelvin
        ), current_offset


@dataclass
class MultiZoneEffectParameter:
    """Auto-generated field structure."""

    parameter0: int
    parameter1: int
    parameter2: int
    parameter3: int
    parameter4: int
    parameter5: int
    parameter6: int
    parameter7: int

    def pack(self) -> bytes:
        """Pack to bytes."""
        from lifx.protocol import serializer

        result = b""

        # parameter0: uint32
        result += serializer.pack_value(self.parameter0, "uint32")
        # parameter1: uint32
        result += serializer.pack_value(self.parameter1, "uint32")
        # parameter2: uint32
        result += serializer.pack_value(self.parameter2, "uint32")
        # parameter3: uint32
        result += serializer.pack_value(self.parameter3, "uint32")
        # parameter4: uint32
        result += serializer.pack_value(self.parameter4, "uint32")
        # parameter5: uint32
        result += serializer.pack_value(self.parameter5, "uint32")
        # parameter6: uint32
        result += serializer.pack_value(self.parameter6, "uint32")
        # parameter7: uint32
        result += serializer.pack_value(self.parameter7, "uint32")

        return result

    @classmethod
    def unpack(
        cls, data: bytes, offset: int = 0
    ) -> tuple[MultiZoneEffectParameter, int]:
        """Unpack from bytes."""
        from lifx.protocol import serializer

        current_offset = offset
        # parameter0: uint32
        parameter0, current_offset = serializer.unpack_value(
            data, "uint32", current_offset
        )
        # parameter1: uint32
        parameter1, current_offset = serializer.unpack_value(
            data, "uint32", current_offset
        )
        # parameter2: uint32
        parameter2, current_offset = serializer.unpack_value(
            data, "uint32", current_offset
        )
        # parameter3: uint32
        parameter3, current_offset = serializer.unpack_value(
            data, "uint32", current_offset
        )
        # parameter4: uint32
        parameter4, current_offset = serializer.unpack_value(
            data, "uint32", current_offset
        )
        # parameter5: uint32
        parameter5, current_offset = serializer.unpack_value(
            data, "uint32", current_offset
        )
        # parameter6: uint32
        parameter6, current_offset = serializer.unpack_value(
            data, "uint32", current_offset
        )
        # parameter7: uint32
        parameter7, current_offset = serializer.unpack_value(
            data, "uint32", current_offset
        )

        return (
            cls(
                parameter0=parameter0,
                parameter1=parameter1,
                parameter2=parameter2,
                parameter3=parameter3,
                parameter4=parameter4,
                parameter5=parameter5,
                parameter6=parameter6,
                parameter7=parameter7,
            ),
            current_offset,
        )


@dataclass
class MultiZoneEffectSettings:
    """Auto-generated field structure."""

    instanceid: int
    effect_type: FirmwareEffect
    speed: int
    duration: int
    parameter: MultiZoneEffectParameter

    def pack(self) -> bytes:
        """Pack to bytes."""
        from lifx.protocol import serializer

        result = b""

        # instanceid: uint32
        result += serializer.pack_value(self.instanceid, "uint32")
        # effect_type: FirmwareEffect (enum)
        result += serializer.pack_value(int(self.effect_type), "uint8")
        # Reserved 2 bytes
        result += serializer.pack_reserved(2)
        # speed: uint32
        result += serializer.pack_value(self.speed, "uint32")
        # duration: uint64
        result += serializer.pack_value(self.duration, "uint64")
        # Reserved 4 bytes
        result += serializer.pack_reserved(4)
        # Reserved 4 bytes
        result += serializer.pack_reserved(4)
        # parameter: MultiZoneEffectParameter
        result += self.parameter.pack()

        return result

    @classmethod
    def unpack(
        cls, data: bytes, offset: int = 0
    ) -> tuple[MultiZoneEffectSettings, int]:
        """Unpack from bytes."""
        from lifx.protocol import serializer

        current_offset = offset
        # instanceid: uint32
        instanceid, current_offset = serializer.unpack_value(
            data, "uint32", current_offset
        )
        # effect_type: FirmwareEffect (enum)
        effect_type_raw, current_offset = serializer.unpack_value(
            data, "uint8", current_offset
        )
        effect_type = FirmwareEffect(effect_type_raw)
        # Skip reserved 2 bytes
        current_offset += 2
        # speed: uint32
        speed, current_offset = serializer.unpack_value(data, "uint32", current_offset)
        # duration: uint64
        duration, current_offset = serializer.unpack_value(
            data, "uint64", current_offset
        )
        # Skip reserved 4 bytes
        current_offset += 4
        # Skip reserved 4 bytes
        current_offset += 4
        # parameter: MultiZoneEffectParameter
        parameter, current_offset = MultiZoneEffectParameter.unpack(
            data, current_offset
        )

        return (
            cls(
                instanceid=instanceid,
                effect_type=effect_type,
                speed=speed,
                duration=duration,
                parameter=parameter,
            ),
            current_offset,
        )


@dataclass
class TileAccelMeas:
    """Auto-generated field structure."""

    x: int
    y: int
    z: int

    def pack(self) -> bytes:
        """Pack to bytes."""
        from lifx.protocol import serializer

        result = b""

        # x: int16
        result += serializer.pack_value(self.x, "int16")
        # y: int16
        result += serializer.pack_value(self.y, "int16")
        # z: int16
        result += serializer.pack_value(self.z, "int16")

        return result

    @classmethod
    def unpack(cls, data: bytes, offset: int = 0) -> tuple[TileAccelMeas, int]:
        """Unpack from bytes."""
        from lifx.protocol import serializer

        current_offset = offset
        # x: int16
        x, current_offset = serializer.unpack_value(data, "int16", current_offset)
        # y: int16
        y, current_offset = serializer.unpack_value(data, "int16", current_offset)
        # z: int16
        z, current_offset = serializer.unpack_value(data, "int16", current_offset)

        return cls(x=x, y=y, z=z), current_offset


@dataclass
class TileBufferRect:
    """Auto-generated field structure."""

    fb_index: int
    x: int
    y: int
    width: int

    def pack(self) -> bytes:
        """Pack to bytes."""
        from lifx.protocol import serializer

        result = b""

        # fb_index: uint8
        result += serializer.pack_value(self.fb_index, "uint8")
        # x: uint8
        result += serializer.pack_value(self.x, "uint8")
        # y: uint8
        result += serializer.pack_value(self.y, "uint8")
        # width: uint8
        result += serializer.pack_value(self.width, "uint8")

        return result

    @classmethod
    def unpack(cls, data: bytes, offset: int = 0) -> tuple[TileBufferRect, int]:
        """Unpack from bytes."""
        from lifx.protocol import serializer

        current_offset = offset
        # fb_index: uint8
        fb_index, current_offset = serializer.unpack_value(
            data, "uint8", current_offset
        )
        # x: uint8
        x, current_offset = serializer.unpack_value(data, "uint8", current_offset)
        # y: uint8
        y, current_offset = serializer.unpack_value(data, "uint8", current_offset)
        # width: uint8
        width, current_offset = serializer.unpack_value(data, "uint8", current_offset)

        return cls(fb_index=fb_index, x=x, y=y, width=width), current_offset


@dataclass
class TileEffectParameter:
    """Auto-generated field structure."""

    sky_type: TileEffectSkyType
    cloud_saturation_min: int
    cloud_saturation_max: int

    def pack(self) -> bytes:
        """Pack to bytes."""
        from lifx.protocol import serializer

        result = b""

        # sky_type: TileEffectSkyType (enum)
        result += serializer.pack_value(int(self.sky_type), "uint8")
        # Reserved 3 bytes
        result += serializer.pack_reserved(3)
        # cloud_saturation_min: uint8
        result += serializer.pack_value(self.cloud_saturation_min, "uint8")
        # Reserved 3 bytes
        result += serializer.pack_reserved(3)
        # cloud_saturation_max: uint8
        result += serializer.pack_value(self.cloud_saturation_max, "uint8")
        # Reserved 23 bytes
        result += serializer.pack_reserved(23)

        return result

    @classmethod
    def unpack(cls, data: bytes, offset: int = 0) -> tuple[TileEffectParameter, int]:
        """Unpack from bytes."""
        from lifx.protocol import serializer

        current_offset = offset
        # sky_type: TileEffectSkyType (enum)
        sky_type_raw, current_offset = serializer.unpack_value(
            data, "uint8", current_offset
        )
        sky_type = TileEffectSkyType(sky_type_raw)
        # Skip reserved 3 bytes
        current_offset += 3
        # cloud_saturation_min: uint8
        cloud_saturation_min, current_offset = serializer.unpack_value(
            data, "uint8", current_offset
        )
        # Skip reserved 3 bytes
        current_offset += 3
        # cloud_saturation_max: uint8
        cloud_saturation_max, current_offset = serializer.unpack_value(
            data, "uint8", current_offset
        )
        # Skip reserved 23 bytes
        current_offset += 23

        return (
            cls(
                sky_type=sky_type,
                cloud_saturation_min=cloud_saturation_min,
                cloud_saturation_max=cloud_saturation_max,
            ),
            current_offset,
        )


@dataclass
class TileEffectSettings:
    """Auto-generated field structure."""

    instanceid: int
    effect_type: FirmwareEffect
    speed: int
    duration: int
    parameter: TileEffectParameter
    palette_count: int
    palette: list[LightHsbk]

    def pack(self) -> bytes:
        """Pack to bytes."""
        from lifx.protocol import serializer

        result = b""

        # instanceid: uint32
        result += serializer.pack_value(self.instanceid, "uint32")
        # effect_type: FirmwareEffect (enum)
        result += serializer.pack_value(int(self.effect_type), "uint8")
        # speed: uint32
        result += serializer.pack_value(self.speed, "uint32")
        # duration: uint64
        result += serializer.pack_value(self.duration, "uint64")
        # Reserved 4 bytes
        result += serializer.pack_reserved(4)
        # Reserved 4 bytes
        result += serializer.pack_reserved(4)
        # parameter: TileEffectParameter
        result += self.parameter.pack()
        # palette_count: uint8
        result += serializer.pack_value(self.palette_count, "uint8")
        # palette: list[LightHsbk]
        for item in self.palette:
            result += item.pack()

        return result

    @classmethod
    def unpack(cls, data: bytes, offset: int = 0) -> tuple[TileEffectSettings, int]:
        """Unpack from bytes."""
        from lifx.protocol import serializer

        current_offset = offset
        # instanceid: uint32
        instanceid, current_offset = serializer.unpack_value(
            data, "uint32", current_offset
        )
        # effect_type: FirmwareEffect (enum)
        effect_type_raw, current_offset = serializer.unpack_value(
            data, "uint8", current_offset
        )
        effect_type = FirmwareEffect(effect_type_raw)
        # speed: uint32
        speed, current_offset = serializer.unpack_value(data, "uint32", current_offset)
        # duration: uint64
        duration, current_offset = serializer.unpack_value(
            data, "uint64", current_offset
        )
        # Skip reserved 4 bytes
        current_offset += 4
        # Skip reserved 4 bytes
        current_offset += 4
        # parameter: TileEffectParameter
        parameter, current_offset = TileEffectParameter.unpack(data, current_offset)
        # palette_count: uint8
        palette_count, current_offset = serializer.unpack_value(
            data, "uint8", current_offset
        )
        # palette: list[LightHsbk]
        palette = []
        for _ in range(16):
            item, current_offset = LightHsbk.unpack(data, current_offset)
            palette.append(item)

        return (
            cls(
                instanceid=instanceid,
                effect_type=effect_type,
                speed=speed,
                duration=duration,
                parameter=parameter,
                palette_count=palette_count,
                palette=palette,
            ),
            current_offset,
        )


@dataclass
class TileStateDevice:
    """Auto-generated field structure."""

    accel_meas: TileAccelMeas
    user_x: float
    user_y: float
    width: int
    height: int
    supported_frame_buffers: int
    device_version: DeviceStateVersion
    firmware: DeviceStateHostFirmware

    def pack(self) -> bytes:
        """Pack to bytes."""
        from lifx.protocol import serializer

        result = b""

        # accel_meas: TileAccelMeas
        result += self.accel_meas.pack()
        # Reserved 1 bytes
        result += serializer.pack_reserved(1)
        # Reserved 1 bytes
        result += serializer.pack_reserved(1)
        # user_x: float32
        result += serializer.pack_value(self.user_x, "float32")
        # user_y: float32
        result += serializer.pack_value(self.user_y, "float32")
        # width: uint8
        result += serializer.pack_value(self.width, "uint8")
        # height: uint8
        result += serializer.pack_value(self.height, "uint8")
        # supported_frame_buffers: uint8
        result += serializer.pack_value(self.supported_frame_buffers, "uint8")
        # device_version: DeviceStateVersion
        result += self.device_version.pack()
        # firmware: DeviceStateHostFirmware
        result += self.firmware.pack()
        # Reserved 4 bytes
        result += serializer.pack_reserved(4)

        return result

    @classmethod
    def unpack(cls, data: bytes, offset: int = 0) -> tuple[TileStateDevice, int]:
        """Unpack from bytes."""
        from lifx.protocol import serializer

        current_offset = offset
        # accel_meas: TileAccelMeas
        accel_meas, current_offset = TileAccelMeas.unpack(data, current_offset)
        # Skip reserved 1 bytes
        current_offset += 1
        # Skip reserved 1 bytes
        current_offset += 1
        # user_x: float32
        user_x, current_offset = serializer.unpack_value(
            data, "float32", current_offset
        )
        # user_y: float32
        user_y, current_offset = serializer.unpack_value(
            data, "float32", current_offset
        )
        # width: uint8
        width, current_offset = serializer.unpack_value(data, "uint8", current_offset)
        # height: uint8
        height, current_offset = serializer.unpack_value(data, "uint8", current_offset)
        # supported_frame_buffers: uint8
        supported_frame_buffers, current_offset = serializer.unpack_value(
            data, "uint8", current_offset
        )
        # device_version: DeviceStateVersion
        device_version, current_offset = DeviceStateVersion.unpack(data, current_offset)
        # firmware: DeviceStateHostFirmware
        firmware, current_offset = DeviceStateHostFirmware.unpack(data, current_offset)
        # Skip reserved 4 bytes
        current_offset += 4

        return (
            cls(
                accel_meas=accel_meas,
                user_x=user_x,
                user_y=user_y,
                width=width,
                height=height,
                supported_frame_buffers=supported_frame_buffers,
                device_version=device_version,
                firmware=firmware,
            ),
            current_offset,
        )


# Type aliases for convenience
TileDevice = TileStateDevice  # Pythonic alias

# Field name mappings: Python name -> Protocol name
# Used by serializer to translate between conventions
FIELD_MAPPINGS: dict[str, dict[str, str]] = {
    "DeviceStateHostFirmware": {
        "build": "Build",
        "version_minor": "VersionMinor",
        "version_major": "VersionMajor",
    },
    "DeviceStateVersion": {"vendor": "Vendor", "product": "Product"},
    "LightHsbk": {
        "hue": "Hue",
        "saturation": "Saturation",
        "brightness": "Brightness",
        "kelvin": "Kelvin",
    },
    "MultiZoneEffectParameter": {
        "parameter0": "Parameter0",
        "parameter1": "Parameter1",
        "parameter2": "Parameter2",
        "parameter3": "Parameter3",
        "parameter4": "Parameter4",
        "parameter5": "Parameter5",
        "parameter6": "Parameter6",
        "parameter7": "Parameter7",
    },
    "MultiZoneEffectSettings": {
        "duration": "Duration",
        "effect_type": "Type",
        "instanceid": "Instanceid",
        "parameter": "Parameter",
        "speed": "Speed",
    },
    "TileAccelMeas": {"x": "X", "y": "Y", "z": "Z"},
    "TileBufferRect": {"fb_index": "FbIndex", "x": "X", "y": "Y", "width": "Width"},
    "TileEffectParameter": {
        "cloud_saturation_max": "CloudSaturationMax",
        "cloud_saturation_min": "CloudSaturationMin",
        "sky_type": "SkyType",
    },
    "TileEffectSettings": {
        "duration": "Duration",
        "effect_type": "Type",
        "instanceid": "Instanceid",
        "palette": "Palette",
        "palette_count": "PaletteCount",
        "parameter": "Parameter",
        "speed": "Speed",
    },
    "TileStateDevice": {
        "accel_meas": "AccelMeas",
        "device_version": "DeviceVersion",
        "firmware": "Firmware",
        "height": "Height",
        "supported_frame_buffers": "SupportedFrameBuffers",
        "user_x": "UserX",
        "user_y": "UserY",
        "width": "Width",
    },
}
