use std::time::Duration;

use bevy::prelude::*;

const FOX_PATH: &str = "models/alien_naked.glb";

#[derive(Resource)]
struct Animations {
    animations: Vec<AnimationNodeIndex>,
    graph: Handle<AnimationGraph>,
}

pub fn plugin(app: &mut App) {
    app.add_systems(Startup, setup);
    app.add_systems(Update, (setup_once_loaded, toggle_animation));
}

fn setup(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    mut graphs: ResMut<Assets<AnimationGraph>>,
) {
    // Build the animation graph
    let (graph, node_indices) = AnimationGraph::from_clips([
        asset_server.load(GltfAssetLabel::Animation(1).from_asset(FOX_PATH)),
        asset_server.load(GltfAssetLabel::Animation(0).from_asset(FOX_PATH)),
    ]);

    // Insert a resource with the current scene information
    let graph_handle = graphs.add(graph);
    commands.insert_resource(Animations {
        animations: node_indices,
        graph: graph_handle,
    });

    // Fox
    commands
        .spawn(SceneRoot(
            asset_server.load(GltfAssetLabel::Scene(0).from_asset(FOX_PATH)),
        ))
        .insert(Name::from("Alien"));
}

fn setup_once_loaded(
    mut commands: Commands,
    animations: Res<Animations>,
    mut players: Query<(Entity, &mut AnimationPlayer), Added<AnimationPlayer>>,
) {
    for (entity, mut player) in &mut players {
        let mut transitions = AnimationTransitions::new();

        // Make sure to start the animation via the `AnimationTransitions`
        // component. The `AnimationTransitions` component wants to manage all
        // the animations and will get confused if the animations are started
        // directly via the `AnimationPlayer`.
        transitions
            .play(&mut player, animations.animations[1], Duration::ZERO)
            .repeat();

        commands
            .entity(entity)
            .insert(AnimationGraphHandle(animations.graph.clone()))
            .insert(transitions);
    }
}

fn toggle_animation(
    animations: Res<Animations>,
    mut transitions: Query<(&mut AnimationTransitions, &mut AnimationPlayer)>,
    keys: Res<ButtonInput<KeyCode>>,
    mut animation_index: Local<u32>,
) {
    if keys.just_pressed(KeyCode::KeyE) {
        for (mut transition, mut player) in &mut transitions {
            transition
                .play(
                    &mut player,
                    animations.animations[*animation_index as usize],
                    Duration::from_secs(1),
                )
                .repeat();
        }

        *animation_index ^= 1; // Toggle between 0 and 1
    }
}
