use bevy::prelude::*;
use monologue_trees::debug::*;

fn main() {
    App::new()
        .add_plugins((
            DefaultPlugins.set(WindowPlugin {
                primary_window: Some(Window {
                    title: "Audio Inspect".into(),
                    resolution: (640., 480.).into(),
                    ..default()
                }),
                ..default()
            }),
            DebugInfoPlugin,
        ))
        .add_systems(PreStartup, (load,))
        .add_systems(Startup, (init,))
        .add_systems(Update, (save, update, sort_buttons))
        .run()
}

/// Stores audio handles so they don't get dropped
#[derive(Component, Debug)]
struct AudioItem(Handle<AudioSource>);

#[derive(Component)]
struct Container;

///
/// Load audio assets
/// TODO: Does this load new items when they're added to the folder?
fn load(server: Res<AssetServer>) {
    // To prevent handles from being dropped,
    // they are stored on entities created triggered on AssetEvent<AudioSource>::Created
    let _yeet = server.load_folder("audio").expect("Load audios");
}

///
/// Initialize audio inspector UI
fn init(mut commands: Commands) {
    commands.spawn(Camera3dBundle { ..default() });

    commands.spawn((
        NodeBundle {
            style: Style {
                width: Val::Percent(100.0),
                height: Val::Percent(100.0),
                align_items: AlignItems::FlexStart,
                align_content: AlignContent::FlexStart,
                flex_direction: FlexDirection::Row,
                flex_wrap: FlexWrap::Wrap,
                ..default()
            },
            background_color: BackgroundColor(Color::MIDNIGHT_BLUE),
            ..default()
        },
        Container,
    ));
}

///
/// Save loaded audio sources to entities
fn save(
    mut audio_load_events: EventReader<AssetEvent<AudioSource>>,
    server: Res<AssetServer>,
    mut commands: Commands,
    container_q: Query<Entity, With<Container>>,
) {
    for event in audio_load_events.iter() {
        match event {
            AssetEvent::Created { handle } => {
                let style = TextStyle {
                    color: Color::BLACK,
                    font_size: 16.0,
                    ..default()
                };
                let handle_path = server
                    .get_handle_path(handle.clone())
                    .expect("Get handle path");
                let path = handle_path.path().to_str().expect("Convert path to str");
                let title = path
                    .split("/")
                    .last()
                    .expect("Extracting filename")
                    .trim_end_matches(".ogg");

                commands
                    .spawn((
                        Name::new(format!("{}", title)),
                        ButtonBundle {
                            style: Style {
                                border: UiRect::all(Val::Px(1.0)),
                                margin: UiRect::all(Val::Px(2.0)),
                                padding: UiRect::all(Val::Px(2.0)),
                                ..default()
                            },
                            border_color: BorderColor(Color::BLACK),
                            ..default()
                        },
                        AudioBundle {
                            source: handle.clone(),
                            settings: PlaybackSettings {
                                mode: bevy::audio::PlaybackMode::Loop,
                                paused: true,
                                ..default()
                            },
                        },
                    ))
                    .with_children(|parent| {
                        parent.spawn(TextBundle::from_section(title, style));
                    })
                    .set_parent(container_q.single());
            }
            AssetEvent::Modified { .. } => {
                debug_assert!(false, "Audio file was modified, not handled!")
            }
            AssetEvent::Removed { .. } => {
                debug_assert!(false, "Audio file was deleted, not handled!")
            }
        }
    }
}

fn sort_buttons(
    mut container: Query<&mut Children, (With<Container>, Changed<Children>)>,
    names: Query<&Name, With<Parent>>,
) {
    container.iter_mut().for_each(|mut children| {
        children.sort_by(|&a, &b| {
            names
                .get(a)
                .expect("Button has name")
                .cmp(names.get(b).expect("Button has name"))
        });
    });
}

/// Update loop; play/pause/volume
fn update(
    mut interactions: Query<
        (&Interaction, &AudioSink, &mut BackgroundColor),
        (With<Button>, Changed<Interaction>),
    >,
) {
    interactions
        .iter_mut()
        .for_each(|(interaction, sink, mut bg_color)| {
            // Toggle audio loop

            // Toggle background color
            bg_color.0 = match interaction {
                Interaction::Hovered => {
                    if bg_color.0 == Color::ORANGE {
                        Color::ORANGE
                    } else {
                        Color::ORANGE_RED
                    }
                }
                Interaction::Pressed => {
                    sink.toggle();

                    if bg_color.0 == Color::ORANGE {
                        Color::WHITE
                    } else {
                        Color::ORANGE
                    }
                }
                Interaction::None => {
                    if bg_color.0 == Color::ORANGE_RED {
                        Color::WHITE
                    } else {
                        bg_color.0
                    }
                }
            }
        })
}
