import math

from util import clamp, rescale


class MovingHead:
    def __init__(self, start_addr):
        self.start_addr = start_addr

        self.pan = 0  # -pi/2 to pi/2
        self.tilt = 0  # -3pi/2 to 3pi/2
        self.speed = 0
        self.dimmer = 0  # 0 to 1
        self.rgbw = (0, 0, 0, 0)

    def __str__(self):

        return (
            f"MovingHead({self.start_addr}): pan={self.pan!r}, "
            f"tilt={self.tilt!r}, speed={self.speed!r}, "
            f"dimmer={self.dimmer!r}, rgbw={self.rgbw!r}"
        )

    def render(self, dst):

        pan = rescale(self.pan, (-1.5 * math.pi, 1.5 * math.pi), (255, 0))
        pan = clamp(int(pan), (0, 255))
        pan_fine = 0

        tilt = rescale(self.tilt, (-0.5 * math.pi, 0.5 * math.pi), (0, 255))
        tilt = clamp(int(tilt), (0, 255))
        tilt_fine = 0

        dimmer = clamp(7 + int(127 * self.dimmer), (7, 134))

        (r, g, b, w) = self.rgbw

        channels = [
            pan,
            pan_fine,
            tilt,
            tilt_fine,
            self.speed,
            dimmer,
            r,
            g,
            b,
            w,
            0,  # color mode
            0,  # auto jump speed
            0,  # control mode
            0,  # reset
        ]

        offset = self.start_addr - 1

        dst[offset : offset + len(channels)] = channels
