//! This example is a show off about the animation system of the engine in a more complex way.
//! The entity in this case doesn't have the sprite component.
//! It has three different sprite sheets to animate.
//! The player is in a constant animation called 'idle'.
//! The player can be animated by movement or by pressing a specific keyboard key for attacking.

use lotus_engine::*;
use std::collections::HashMap;

your_game!(
    WindowConfiguration::default()
        .title("Player Animation".to_string())
        .background_color(Some(Color::by_option(ColorOption::Lightgray))),
    setup,
    update
);

fn setup(context: &mut Context) {
    context.game_loop_listener.fps_cap(120);

    let idle: SpriteSheet = SpriteSheet::new(
        "textures/animations/player/idle.png".to_string(),
        LoopingState::Repeat,
        (512.0, 512.0),
        0.1,
        1,
        10,
        (0..=9).collect()
    );
    let attack: SpriteSheet = SpriteSheet::new(
        "textures/animations/player/attack.png".to_string(),
        LoopingState::Repeat,
        (512.0, 512.0),
        0.1,
        1,
        7,
        (0..=6).collect()
    );
    let walk: SpriteSheet = SpriteSheet::new(
        "textures/animations/player/walk.png".to_string(),
        LoopingState::Repeat,
        (512.0, 512.0),
        0.1,
        1,
        16,
        (0..=15).collect()
    );

    let mut my_animations: HashMap<String, SpriteSheet> = HashMap::new();
    my_animations.insert("idle".to_string(), idle);
    my_animations.insert("attack".to_string(), attack);
    my_animations.insert("walk".to_string(), walk);

    let mut animation: Animation = Animation::new(my_animations);
    animation.play("idle".to_string());

    context.commands.spawn(vec![
        Box::new(animation),
        Box::new(Velocity::new(Vector2::new(0.5, 0.5)))
    ]);
}

fn update(context: &mut Context) {
    let keyboard_input: KeyboardInput = context.world.get_resource_cloned::<KeyboardInput>().unwrap();

    if keyboard_input.is_key_pressed(KeyboardKey::Semicolon) {
        let mut query: Query = Query::new(&context.world).with::<Fps>();

        if let Some(_) = query.entities_with_components().unwrap().first() {
            context.commands.hide_fps();
        } else {
            context.commands.show_fps(context.game_loop_listener.current_fps, Color::by_option(ColorOption::Black));
        }
    }
    move_player(context, keyboard_input.clone());
    attack(context, keyboard_input);
}

fn move_player(context: &mut Context, keyboard_input: KeyboardInput) {
    let mut query: Query = Query::new(&context.world).with::<Animation>();
    let result: Entity = query.entities_with_components().unwrap().first().unwrap().clone();
    let mut animation: ComponentRefMut<'_, Animation> = context.world.get_entity_component_mut::<Animation>(&result).unwrap();
    let mut transform: ComponentRefMut<'_, Transform> = context.world.get_entity_component_mut::<Transform>(&result).unwrap();
    let velocity: ComponentRef<'_, Velocity> = context.world.get_entity_component::<Velocity>(&result).unwrap();

    if keyboard_input.is_key_pressed(KeyboardKey::KeyW) {
        let y: f32 = transform.position.y + velocity.y * context.delta;
        transform.set_position_y(&context.render_state, y);
    } else if keyboard_input.is_key_pressed(KeyboardKey::KeyS) {
        let y: f32 = transform.position.y - velocity.y * context.delta;
        transform.set_position_y(&context.render_state, y);
    } else if keyboard_input.is_key_pressed(KeyboardKey::KeyD) {
        let x: f32 = transform.position.x + velocity.x * context.delta;
        transform.set_position_x(&context.render_state, x);
    } else if keyboard_input.is_key_pressed(KeyboardKey::KeyA) {
        let x: f32 = transform.position.x - velocity.x * context.delta;
        transform.set_position_x(&context.render_state, x);
    }

    if keyboard_input.is_some_of_keys_pressed(vec![KeyboardKey::KeyW, KeyboardKey::KeyS, KeyboardKey::KeyA, KeyboardKey::KeyD]) {
        animation.play("walk".to_string());
    }

    if keyboard_input.is_some_of_keys_released(vec![KeyboardKey::KeyW, KeyboardKey::KeyS, KeyboardKey::KeyA, KeyboardKey::KeyD]) {
        animation.stop("walk".to_string());
    }
}

fn attack(context: &mut Context, keyboard_input: KeyboardInput) {
    let mut query: Query = Query::new(&context.world).with::<Animation>();
    let result: Entity = query.entities_with_components().unwrap().first().unwrap().clone();
    let mut animation: ComponentRefMut<'_, Animation> = context.world.get_entity_component_mut::<Animation>(&result).unwrap();

    if keyboard_input.is_key_pressed(KeyboardKey::Space) {
        animation.play("attack".to_string());
    }

    if keyboard_input.is_key_released(KeyboardKey::Space) {
        animation.stop("attack".to_string());
    }
}
