use crate::camera::MainCamera;
use bevy::prelude::*;
use bevy_sprite3d::Sprite3dPlugin;

#[derive(Component, Reflect)]
#[reflect(Component)]
pub struct Billboard;

pub fn plugin(app: &mut App) {
    if !app.is_plugin_added::<Sprite3dPlugin>() {
        app.add_plugins(Sprite3dPlugin);
    }

    app.register_type::<Billboard>();
    app.add_systems(Update, (face_camera, face_camera_no_parent));
}

fn face_camera(
    cam_query: Query<&GlobalTransform, With<MainCamera>>,
    mut query: Query<
        (&mut Transform, &ChildOf, &InheritedVisibility),
        (With<Billboard>, Without<MainCamera>),
    >,
    parent_transform: Query<&GlobalTransform>,
) {
    let Ok(cam_transform) = cam_query.single() else {
        return;
    };

    for (mut transform, parent, visible) in query.iter_mut() {
        if !matches!(*visible, InheritedVisibility::VISIBLE) {
            continue;
        }

        let Ok(parent_global) = parent_transform.get(parent.parent()) else {
            continue;
        };

        let target = cam_transform.reparented_to(parent_global);
        transform.look_at(target.translation, Vec3::Y);
    }
}

fn face_camera_no_parent(
    cam_query: Query<&GlobalTransform, With<MainCamera>>,
    mut query: Query<&mut Transform, (With<Billboard>, Without<MainCamera>, Without<ChildOf>)>,
) {
    let Ok(cam_transform) = cam_query.single() else {
        return;
    };
    for mut transform in query.iter_mut() {
        transform.look_at(cam_transform.translation(), Vec3::Y);
    }
}
