
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

extern crate rodio;
mod base;
use base::*;
use imgui::*;
use walkdir::WalkDir;
mod support_ogl;
// mod support_glium;
use env_logger;
use std::sync::Arc;
// use log::*;

fn collect_sounds (root: &str) -> Vec<Sound> {
    WalkDir::new(root)
    .into_iter()
    .filter_map(|e| e.ok())
    .filter(|e| e.path().is_file())
    .map(|f| Sound::new(&f.path().to_path_buf()))
    .filter_map(|e| e.ok())
    .collect()
}

fn collect_patterns (root: &str) -> Vec<Pattern> {
    WalkDir::new(root)
    .into_iter()
    .filter_map(|e| e.ok())
    .filter(|e| e.path().is_file())
    .map(|f| Pattern::load(f.path()))
    // .map(|p| dbg!(p))
    .filter_map(|e| e.ok())
    // .map(|p| Arc::new(p))
    .collect()
}

fn main() {

    env_logger::init();
    // let dev = rodio::default_output_device().unwrap();
    let dev = Arc::new(rodio::default_output_device().unwrap());
    
    let mut sounds = collect_sounds("media");
    let mut patterns = collect_patterns("patterns");
    
    let mut timeline = Timeline::default();
    
    let mut pattern_col: usize = 0;
    let mut pattern_row: usize = 0;
    
    let mut active_pattern = Pattern::default();
    // let mut active_pattern = Arc::new(Pattern::default());
    let mut active_sound: Option<Sound> = None;

    let mut system = support_ogl::init(file!());
    let display = system.imgui.io().display_size;
    let pixel_count = display[0]*display[1];
    dbg!(pixel_count);
    let mut style = system.imgui.style_mut();
    style.window_rounding = 1.5;
    style.anti_aliased_lines = false;
    style.anti_aliased_fill = false;

    // ui.push_style_color();
    
    // style.colors[StyleColor::Text]                   = ImVec4(1.00, 1.00, 1.00, 1.00);
    // // style.colors[ImGuiCol_WindowBg]               = ImVec4(0.03f, 0.03f, 0.03f, 1.00f);
    // // style.colors[ImGuiCol_FrameBg]                = ImVec4(0.07f, 0.05f, 0.27f, 1.00f);
    // // style.colors[ImGuiCol_FrameBgHovered]         = ImVec4(0.11f, 0.08f, 0.44f, 1.00f);
    // // style.colors[ImGuiCol_FrameBgActive]          = ImVec4(0.07f, 0.05f, 0.27f, 1.00f);
    // // style.colors[ImGuiCol_TitleBg]                = ImVec4(0.11f, 0.11f, 0.11f, 1.00f);
    // // style.colors[ImGuiCol_TitleBgActive]          = ImVec4(0.14f, 0.05f, 0.96f, 1.00f);
    // // style.colors[ImGuiCol_ScrollbarBg]            = ImVec4(0.03f, 0.03f, 0.03f, 1.00f);
    // // style.colors[ImGuiCol_CheckMark]              = ImVec4(0.07f, 0.05f, 0.27f, 1.00f);
    // // style.colors[ImGuiCol_SliderGrab]             = ImVec4(0.07f, 0.05f, 0.27f, 1.00f);
    // // style.colors[ImGuiCol_SliderGrabActive]       = ImVec4(0.07f, 0.05f, 0.27f, 1.00f);
    // // style.colors[ImGuiCol_Button]                 = ImVec4(0.07f, 0.05f, 0.27f, 1.00f);
    // // style.colors[ImGuiCol_ButtonHovered]          = ImVec4(0.18f, 0.12f, 0.78f, 1.00f);
    // // style.colors[ImGuiCol_ButtonActive]           = ImVec4(0.20f, 0.13f, 0.88f, 1.00f);
    // // style.colors[ImGuiCol_Header]                 = ImVec4(0.07f, 0.05f, 0.27f, 1.00f);
    // // style.colors[ImGuiCol_SeparatorHovered]       = ImVec4(0.13f, 0.07f, 0.78f, 1.00f);
    // // style.colors[ImGuiCol_SeparatorActive]        = ImVec4(0.07f, 0.05f, 0.27f, 1.00f);
    // // style.colors[ImGuiCol_ResizeGrip]             = ImVec4(0.07f, 0.05f, 0.27f, 1.00f);
    // // style.colors[ImGuiCol_ResizeGripHovered]      = ImVec4(0.19f, 0.12f, 0.85f, 1.00f);
    // // style.colors[ImGuiCol_ResizeGripActive]       = ImVec4(0.07f, 0.05f, 0.27f, 1.00f);
    // // style.colors[ImGuiCol_Tab]                    = ImVec4(0.07f, 0.05f, 0.27f, 1.00f);
    // // style.colors[ImGuiCol_TabHovered]             = ImVec4(0.15f, 0.05f, 0.27f, 1.00f);
    // // style.colors[ImGuiCol_TabActive]              = ImVec4(0.21f, 0.14f, 0.91f, 1.00f);
    // // style.colors.
    
    let PURPLE = [0.07, 0.05, 0.27, 1.00];
    system.main_loop(move |_, ui| {

        let colors = ui.push_style_colors(&[
            (StyleColor::FrameBg, PURPLE),
            (StyleColor::Button, PURPLE),
            (StyleColor::TitleBgActive, PURPLE),
            (StyleColor::ResizeGrip, PURPLE),
            (StyleColor::CheckMark, PURPLE),
            (StyleColor::Tab, PURPLE),
        ]);


        Window::new(im_str!("sources"))
            // .resizable(false)
            .position([400.0, 140.0], Condition::Appearing)
            .collapsible(false)
            // .always_auto_resize(true)
            .size([300.0, 300.0], Condition::FirstUseEver)
            .build(ui, || {

                // ui.show_default_style_editor();

                ui.tree_node(im_str!("snds"))
                .opened(true, Condition::Appearing)
                .build(|| {
                    for s in &mut sounds {
                        ui.tree_node(&im_str!("{}", s.name)).build(|| {
                            // ui.same_line(0.0);
                            // if ui.small_button(im_str!("add to pattern")) {
                            //     active_pattern.sounds[pattern_row][pattern_col] = Some(s.clone());
                            // }
                            if ui.small_button(im_str!("load")) {
                                active_sound = Some(s.clone());
                            }
                            ui.same_line(0.0);
                            if ui.small_button(im_str!("play")) {
                                s.play(&dev);
                            }
                        });
                    }
                });
            });

        Window::new(im_str!("patterns"))
            // .resizable(false)
            .position([400.0, 140.0], Condition::Appearing)
            .collapsible(true)
            .size([300.0, 300.0], Condition::FirstUseEver)
            .build(ui, || {
                ui.tree_node(im_str!("patterns"))
                .opened(true, Condition::Appearing)
                .build(|| {
                    for p in &mut patterns {
                        ui.tree_node(&im_str!("{}", p.name)).build(|| {
                            // ui.same_line(0.0);
                            if ui.small_button(im_str!("load")) {
                                active_pattern = p.clone();
                            }
                            ui.same_line(0.0);
                            if ui.small_button(im_str!("play")) {
                                p.play(&dev);
                            }
                        });
                    }
                });
            });

        // PATTERN WINDOW ====================================
        Window::new(im_str!("pattern"))
            .size([300.0, 100.0], Condition::FirstUseEver)
            .build(ui, || {

                if ui.small_button(&im_str!("increase length")) {active_pattern.extend_length(1);}
                ui.same_line(0.0);
                if ui.small_button(&im_str!("add trk")) {active_pattern.extend_row(1);}
                ui.same_line(0.0);
                if ui.small_button(&im_str!("save")) {active_pattern.save();}
                ui.same_line(0.0);
                if ui.small_button(&im_str!("load")) {}
                // if ui.small_button(&im_str!("theme")) {
                //     let col: Vec<[f32; 4]> = style.clone().colors.iter().map(|x| x.clone()).collect();
                //     let s = Theme {colors: col};
                //     dbg!(&s);

                // }

    
                let mut imstr_name = ImString::from(active_pattern.name.clone());
                if ui.input_text(&im_str!("name"), &mut imstr_name)
                    .resize_buffer(true)
                    .auto_select_all(true)
                    .build() {
                    active_pattern.name = imstr_name.to_string();
                };
                
                let button_size: f32 = 16.0;

                ui.drag_int(im_str!("repeat"), &mut active_pattern.repeat)
                    .max(32)
                    .speed(0.05)
                    .build();
                
                ui.drag_int(im_str!("bpm"), &mut active_pattern.bpm).build();

                ui.text(im_str!("loc     "));
                for x in 0..active_pattern.xsize {
                    ui.same_line(0.0);
                    ui.button(&im_str!("{}", x+1), [button_size, button_size]);
                }
                

                for y in 0..active_pattern.ysize {
                    ui.text(im_str!("{}", active_pattern.name_from_row(y)));
                    for x in 0..active_pattern.xsize {
                        let label = match &active_pattern.sounds.get(&(x,y)) {
                            Some(_s) => "X",
                            None => " "
                        };
                        
                        ui.same_line(0.0);
                        if ui.button(&im_str!("{}##{}{}", label, y, x), [button_size, button_size]) {
                            pattern_col = x;
                            pattern_row = y;
                            match &active_sound {
                                Some(snd) => {active_pattern.sounds.insert((x,y),  snd.clone());},
                                None => {active_pattern.sounds.remove(&(x,y));}
                            }
                        }
                        
                        
                    }
                    
                    ui.same_line(0.0);
                    if ui.small_button(&im_str!("replace src##{}",y) ){
                        if let Some(acs) = &active_sound {
                            active_pattern.replace_sound_sources(acs, y);
                        }
                    }
                    ui.same_line(0.0);
                    if ui.small_button(&im_str!("clr##{}", y) ){
                        active_pattern.clear_sounds(y);
                    }

                }

                ui.text(im_str!("pat {} {}", pattern_col, pattern_row));
                if ui.small_button(&im_str!("play")) {
                    active_pattern.play(&dev);
                }

        
            });
    
            Window::new(im_str!("sound"))
            .size([300.0, 100.0], Condition::FirstUseEver)
            .build(ui, || {
                // let snd = &active_bar.sounds[pattern_col];
                if let Some(s) = &mut active_sound {
                    ui.text(im_str!("name   {}", s.name));
                    // let _ = DragFloat::new()
                    ui.drag_float(im_str!("volume"), &mut s.volume)
                        .min(-1.0)
                        .max(2.0)
                        .speed(0.01)
                        .build();
                    ui.drag_float(im_str!("speed"), &mut s.speed)
                        .min(0.0)
                        .max(2.0)
                        .speed(0.01)
                        .build();
                    ui.drag_int(im_str!("roll"), &mut s.roll)
                        .max(32)
                        .speed(0.05)
                        .build();

                    ui.checkbox(im_str!("reverse"), &mut s.reverse);
                
                    if ui.small_button(&im_str!("play")) {
                        s.play(&dev);
                    }
                
                }
                if ui.small_button(&im_str!("clear")) {
                    active_sound = None;
                }
            });
    
            Window::new(im_str!("tracks"))
            .size([300.0, 100.0], Condition::FirstUseEver)
            .build(ui, || {
               
                if ui.small_button(&im_str!("add")) {
                    active_pattern.play(&dev);
                }
            });
    
            Window::new(im_str!("settings"))
            .size([300.0, 100.0], Condition::FirstUseEver)
            .build(ui, || {
               
                let mut scale = 1.0;
                if ui.drag_float(im_str!("speed"), &mut scale)
                .min(0.0)
                .max(3.0)
                .speed(0.01)
                .build() {
                    // let s = system.imgui.style_mut();
                    
                    // s.scale_all_sizes(scale);

                }

            });


            colors.pop(&ui);
    
        });
}
