use std::f32::consts::TAU;

use bevy::prelude::*;

use crate::core::counter::KirbyHitCountThisFrame;

#[derive(Component)]
pub struct MyCamera {
    shaking_intensity_factor: f32,
    shaking_reset_speed: f32,
}

pub fn spawn_camera(mut commands: Commands) {
    let mycam = commands
        .spawn((
            MyCamera { shaking_intensity_factor: 10.0, shaking_reset_speed: 100.0 },
            Transform::from_translation(Vec3::ZERO),
        ))
        .id();
    commands.entity(mycam).with_child((Camera2d, Transform::from_xyz(0.0, 0.0, 0.0)));
}

pub fn camera_shake(
    time: Res<Time<Fixed>>,
    kirby_hit_count: Res<KirbyHitCountThisFrame>,
    parent_query: Query<(&MyCamera, &Children)>,
    mut children_query: Query<&mut Transform, With<Camera2d>>,
) {
    let (parent, children) = parent_query.single().expect("Expect exactly one MyCamera entity");
    let child = children.first().expect("MyCamera must have at least one child Camera2d");
    let mut child_transform = children_query.get_mut(*child).expect("Camera child must have a Transform and Camera2d");

    let rand_angle = rand::random_range(0.0..TAU);
    let rand_vec = Vec2::from_angle(rand_angle);
    let shaking_strength = kirby_hit_count.get_count() as f32 * parent.shaking_intensity_factor;
    let shaking_vec = rand_vec * shaking_strength;
    let mut child_translation = child_transform.translation.clone();
    child_translation += shaking_vec.extend(0.0);
    child_translation -= child_translation * parent.shaking_reset_speed * time.delta_secs();
    child_transform.translation.x = child_translation.x;
    child_transform.translation.y = child_translation.y;
    // println!("{:?}", child_transform.translation);
}

pub struct MyCameraPlugin;

impl Plugin for MyCameraPlugin {
    fn build(&self, app: &mut App) {
        app.add_systems(Startup, spawn_camera).add_systems(FixedPostUpdate, camera_shake);
    }
}
