use std::f32::consts::{FRAC_PI_2, PI};

use crate::util::rescale;

pub struct MovingHead {
    start_addr: usize,

    pub pan: f32,    // -3pi/2 to 3pi/2
    pub tilt: f32,   // -pi/2 to pi/2
    pub dimmer: f32, // 0 to 1
    pub rgbw: (u8, u8, u8, u8),
    pub speed: u8, // reversed
}

impl MovingHead {
    pub fn new(start_addr: usize) -> Self {
        Self {
            start_addr,

            pan: 0f32,
            tilt: 0f32,
            speed: 0u8,
            dimmer: 0f32,
            rgbw: (0u8, 0u8, 0u8, 0u8),
        }
    }
}

pub trait DMXFixture {
    fn render(&self, dst: &mut [u8]);
}

impl DMXFixture for MovingHead {
    fn render(&self, dst: &mut [u8]) {
        let pan = rescale(self.pan, (-1.5 * PI, 1.5 * PI), (255.0, 0.0)) as u8;
        let pan_fine = 0;

        let tilt = rescale(self.tilt, (-1.0 * FRAC_PI_2, FRAC_PI_2), (0.0, 255.0)) as u8;
        let tilt_fine = 0;

        let dimmer = (7 + (127.0 * self.dimmer) as u8).clamp(7, 134);

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

        let offset = self.start_addr - 1;

        let channels = [
            pan, pan_fine, tilt, tilt_fine, self.speed, dimmer, r, g, b, w, 0, 0, 0, 0,
        ];

        dst[offset..offset + channels.len()].copy_from_slice(&channels);
    }
}
