mod capture;
mod dmx_controller;
mod dsp;
mod fixtures;
mod layers;
mod util;

use std::{sync::{Arc, Mutex}, thread, time::Duration};

use anyhow::Result;
use layers::{OutputLayer, beat_detector::BeatDetectinator, hsl_cycle::HSLCycle};
use sdl2::{event::Event, keyboard::Keycode, pixels::Color, rect::Rect};

use crate::dmx_controller::controller_thread;
use crate::fixtures::MovingHead;

const FPS: usize = 50;

fn main() -> Result<()> {
    // dmx thread

    let dmx_running = Arc::new(Mutex::new(true));
    let movingheads = Arc::new(Mutex::new([
        MovingHead::new(1),
        MovingHead::new(15),
        MovingHead::new(29),
        MovingHead::new(43),
    ]));

    let dmx_thread = {
        let dmx_running = dmx_running.clone();
        let movingheads = movingheads.clone();
        thread::spawn(move || controller_thread(dmx_running, movingheads))
    };

    // output layers

    let mut beat_detector = BeatDetectinator::new();
    let mut hsl_cycle = HSLCycle::new(Duration::from_secs(5));

    // sdl

    let sdl = sdl2::init().unwrap();
    let sdl_video = sdl.video().unwrap();

    let window = sdl_video
        .window("Beat Detectinator", 800, 600)
        .resizable()
        .build()?;
    let mut canvas = window.into_canvas().build()?;
    let texture_creator = canvas.texture_creator();
    let texture_size = 250;
    let mut texture = texture_creator.create_texture_target(
        canvas.default_pixel_format(),
        texture_size,
        texture_size,
    )?;
    
    let frame_duration = Duration::from_secs_f64(1.0 / FPS as f64);

    let mut event_pump = sdl.event_pump().unwrap();

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit { .. }
                | Event::KeyDown {
                    keycode: Some(Keycode::Escape),
                    ..
                } => break 'running,

                event => {
                    // println!("{:?}", event);
                    beat_detector.on_sdl_event(&event);
                    hsl_cycle.on_sdl_event(&event);
                }
            }
        }
        
        beat_detector.tick(frame_duration);
        hsl_cycle.tick(frame_duration);
        
        {
            let mut output = movingheads.lock().unwrap();
            beat_detector.update_dmx(&mut *output);
            hsl_cycle.update_dmx(&mut *output);
        }

        canvas.set_draw_color(Color::RGB(0, 0, 0));
        canvas.clear();

        canvas.with_texture_canvas(&mut texture, |canvas| {
            beat_detector.draw_sdl(canvas, texture_size);
            hsl_cycle.draw_sdl(canvas, texture_size);
        })?;


        let (w, h) = canvas.window().drawable_size();

        let target_rect = if w > h {
            Rect::new(((w - h) / 2) as i32, 0, h, h)
        } else {
            Rect::new(0, ((h - w) / 2) as i32, w, w)
        };

        canvas.copy(&texture, None, Some(target_rect)).unwrap();
        canvas.present();
        thread::sleep(frame_duration);
    }

    {
        let mut dmx_running = dmx_running.lock().unwrap();
        *dmx_running = false;
    }

    dmx_thread.join().unwrap()?;

    Ok(())
}
