// Connect the interface with the button below and modify the code here.
// The output should update in real time as you type :)

// Fixtures library. TODO move this into a separate file

class Fixture {
    address: number
    ctx: Context

    constructor(address: number, ctx: Context) {
        this.address = address;
        this.ctx = ctx;
    }
}

interface GenericRGBW {
    /**
     * Set the brightness
     * 
     * @param value between 0 and 1
     * @param strobe enable strobe (turn off if unsupported)
     */
    setBrightness(value: number, strobe?: boolean): void
    setRGBW(rgb: [number, number, number], w?: number): void
}

class Par extends Fixture implements GenericRGBW {
    setBrightness(value: number, strobe?: boolean) {
        if (strobe || false) {
            this.ctx.set(this.address, 255);
            this.ctx.set(this.address + 7, value * 255);
        } else {
            this.ctx.set(this.address, value * 255);
            this.ctx.set(this.address + 7, 0);
        }
    }

    setRGBW(rgb: [number, number, number], w?: number) {
        let [r, g, b] = rgb;
        this.ctx.set(this.address + 1, r);
        this.ctx.set(this.address + 2, g);
        this.ctx.set(this.address + 3, b);
        this.ctx.set(this.address + 4, w || 0);
    }

    setAUV(a: number, uv: number) {
        this.ctx.set(this.address + 5, a);
        this.ctx.set(this.address + 6, uv);
    }
}

class MovingHead extends Fixture implements GenericRGBW {
    setBrightness(value: number, strobe?: boolean) {
        let out = (strobe || false)
            ? 135 + (239 - 135) * value
            : 8 + (134 - 8) * value;
        this.ctx.set(this.address + 5, out);
    }

    setRGBW(rgb: [number, number, number], w?: number) {
        let [r, g, b] = rgb;
        this.ctx.set(this.address + 6, r);
        this.ctx.set(this.address + 7, g);
        this.ctx.set(this.address + 8, b);
        this.ctx.set(this.address + 9, w || 0);
    }

    /**
     * Rotate the moving head. Pan and tilt are in radians.
     * @param pan between -1.5pi and 1.5pi
     * @param tilt between -0.5pi and 0.5pi
     * @param speed between 0 (fast) and 255 (slow)
     */
    setPanTilt(pan: number, tilt: number, speed?: number) {
        let panRough = (pan + 3 * Math.PI / 2) / (Math.PI * 3) * 256
        panRough = Math.max(0, Math.min(255, panRough))

        let tiltRough = (tilt + Math.PI / 2) / (Math.PI) * 256
        tiltRough = Math.max(0, Math.min(255, tiltRough))

        // TODO
        let panFine = 0
        let tiltFine = 0

        this.ctx.set(this.address + 0, panRough);
        this.ctx.set(this.address + 1, panFine);
        this.ctx.set(this.address + 2, tiltRough);
        this.ctx.set(this.address + 3, tiltFine);
        this.ctx.set(this.address + 4, speed || 0);
    }
}

// ******************
// * CODE GOES HERE *
// ******************

let color = lib.hsl2rgb(360 * t, 100, 50);

let par = new Par(1, ctx);
par.setBrightness(1);
par.setRGBW(color);