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

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

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

pub struct AudioContext {
    _hal: Hal,
    _synthesizer_id: usize,
    metronome_id: usize,
    mixer: MixerHandle,
    synthesizer: SynthesizerHandle,
    metronome: MetronomeHandle,
} 

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), Default::default())
        .expect("Failed to init GTK application");
    app.connect_activate(move |app| ui::init(app, audio_context.clone()));
    app.run(&std::env::args().collect::<Vec<_>>());
}
