use bevy::prelude::*;
use de_construction::EnqueueAssemblyEvent;
use de_core::{
    cleanup::DespawnOnGameExit, gamestate::GameState, objects::ObjectTypeComponent,
    schedule::InputSchedule,
};
use de_gui::{ButtonCommands, GuiCommands, OuterStyle};
use de_objects::SolidObjects;
use de_types::objects::UnitType;
use super::{interaction::InteractionBlocker, HUD_COLOR};
use crate::selection::Selected;
pub(crate) struct ActionBarPlugin;
impl Plugin for ActionBarPlugin {
    fn build(&self, app: &mut App) {
        app.add_systems(OnEnter(GameState::Playing), setup)
            .add_systems(OnExit(GameState::Playing), cleanup)
            .add_systems(
                PostUpdate,
                (
                    detect_update.in_set(ActionBarSet::DetectUpdate),
                    update
                        .run_if(resource_exists_and_changed::<ActiveEntity>)
                        .after(ActionBarSet::DetectUpdate),
                )
                    .run_if(in_state(GameState::Playing)),
            )
            .add_systems(
                InputSchedule,
                button_system.run_if(in_state(GameState::Playing)),
            );
    }
}
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, SystemSet)]
enum ActionBarSet {
    DetectUpdate,
}
#[derive(Resource)]
struct ActionBarNode(Entity);
#[derive(Resource, Default)]
struct ActiveEntity(Option<Entity>);
#[derive(Component)]
struct ButtonAction(UnitType);
fn cleanup(mut commands: Commands) {
    commands.remove_resource::<ActionBarNode>();
    commands.remove_resource::<ActiveEntity>();
}
fn setup(mut commands: Commands) {
    let entity = commands
        .spawn((
            NodeBundle {
                style: Style {
                    width: Val::Percent(60.),
                    height: Val::Percent(15.),
                    position_type: PositionType::Absolute,
                    left: Val::Percent(20.),
                    right: Val::Percent(80.),
                    top: Val::Percent(85.),
                    bottom: Val::Percent(100.),
                    ..default()
                },
                background_color: HUD_COLOR.into(),
                ..default()
            },
            DespawnOnGameExit,
            InteractionBlocker,
        ))
        .id();
    commands.insert_resource(ActionBarNode(entity));
    commands.init_resource::<ActiveEntity>();
}
fn detect_update(mut active: ResMut<ActiveEntity>, selected: Query<Entity, With<Selected>>) {
    let new = selected.get_single().ok();
    if active.0 != new {
        active.0 = new;
    }
}
fn update(
    mut commands: GuiCommands,
    solids: SolidObjects,
    bar_node: Res<ActionBarNode>,
    active: Res<ActiveEntity>,
    objects: Query<&ObjectTypeComponent>,
) {
    commands.entity(bar_node.0).despawn_descendants();
    let Some(active) = active.0 else { return };
    let object_type = *objects.get(active).unwrap();
    if let Some(factory) = solids.get(*object_type).factory() {
        for &unit in factory.products() {
            spawn_button(&mut commands, bar_node.0, unit);
        }
    }
}
fn spawn_button(commands: &mut GuiCommands, parent: Entity, unit: UnitType) {
    let button = commands
        .spawn_button(
            OuterStyle {
                width: Val::Percent(10.),
                height: Val::Percent(80.),
                margin: UiRect::new(
                    Val::Percent(0.),
                    Val::Percent(0.),
                    Val::Percent(2.),
                    Val::Percent(2.),
                ),
            },
            unit.to_string().chars().next().unwrap(),
        )
        .insert(ButtonAction(unit))
        .id();
    commands.entity(parent).add_child(button);
}
fn button_system(
    active: Res<ActiveEntity>,
    interactions: Query<(&Interaction, &ButtonAction), Changed<Interaction>>,
    mut events: EventWriter<EnqueueAssemblyEvent>,
) {
    for (&interaction, action) in interactions.iter() {
        if let Interaction::Pressed = interaction {
            events.send(EnqueueAssemblyEvent::new(active.0.unwrap(), action.0));
        }
    }
}