use gio::prelude::*;
use std::sync::Arc;

mod audio;
mod globals;
mod ui;
mod utils;

use audio::hal::Hal;
use audio::sources::metronome::{self, Metronome};
use audio::sources::mixer::{self, Mixer};
use audio::sources::synthesizer::{self, Synthesizer};

pub struct AudioContext {
    _hal: Hal,
    _synthesizer_id: usize,
    metronome_id: usize,
    mixer: mixer::Handle,
    synthesizer: synthesizer::Handle,
    metronome: metronome::Handle,
}

fn main() {
    // Initialize audio
    let hal = Hal::new().unwrap();
    let sample_rate = hal.get_sample_rate();
    let notes_number = ui::keyboard::NOTES_NUMBER;

    let (metronome, metronome_handle) = Metronome::new(sample_rate);
    let (synthesizer, synthesizer_handle) = Synthesizer::new(notes_number, sample_rate);

    let (mut mixer, mixer_handle) = Mixer::new();
    let synthesizer_id = mixer.add(Box::new(synthesizer), true, 0.5);
    let metronome_id = mixer.add(Box::new(metronome), false, 0.3);

    hal.start(Box::new(mixer));

    let audio_context = Arc::new(AudioContext {
        _hal: hal,
        _synthesizer_id: synthesizer_id,
        metronome_id,
        mixer: mixer_handle,
        synthesizer: synthesizer_handle,
        metronome: metronome_handle,
    });

    // Initialize UI
    let app = gtk::Application::new(Some(globals::APP_ID), gio::ApplicationFlags::default());
    app.connect_activate(move |app| ui::init(app, audio_context.clone()));
    app.run_with_args(&std::env::args().collect::<Vec<_>>());
}
