use bevy::prelude::*;
use bevy_rapier3d::prelude::ColliderDisabled;

use crate::{
    level_instantiation::Door, player::{toolbar::Item, Player, PlayerAction}, util::single_mut
};

use super::{Interact, ui::InteractionOpportunity};

pub fn plugin(_app: &mut App) {}

pub fn handle_pick_up(
    mut commands: Commands,
    // current action
    mut player_query: Query<(&PlayerAction, &Transform, &mut Item), With<Player>>,
    mut vis_query: Query<&mut Visibility>,
    children: Query<&mut Children>,

    mut item_transform: Query<&mut Transform, (With<Interact>, Without<Player>)>,
    // current interactable
    mut interaction_opportunity: ResMut<InteractionOpportunity>,
) {
    let (action, transform, mut item) = single_mut!(player_query);
    if *action == PlayerAction::PickUp {
        // take out the interaction, because we are picking it up
        let Some(target) = interaction_opportunity.0.take() else {
            return;
        };
        let replaced = item.set_item(target);
        if let Ok(mut vis) = vis_query.get_mut(target) {
            *vis = Visibility::Hidden;
        }
        if let Ok(colliders) = children.get(target) {
            for &collider in colliders {
                commands.entity(collider).insert(ColliderDisabled);
            }
        }
        if let Some(dropped) = replaced {
            if let Ok(mut vis) = vis_query.get_mut(dropped) {
                *vis = Visibility::Visible;
            }
            if let Ok(colliders) = children.get(dropped) {
                for &collider in colliders {
                    commands.entity(collider).remove::<ColliderDisabled>();
                }
            }
            // for simplicities sake, set the transform of the item that is dropped to that of the player
            let mut item_transform = item_transform.get_mut(dropped).unwrap();
            *item_transform = *transform;
        }
    }
}

pub fn handle_drop(
    mut commands: Commands,
    // current action
    mut player_query: Query<(&PlayerAction, &Transform, &mut Item), With<Player>>,
    mut vis_query: Query<&mut Visibility>,
    mut item_transform: Query<&mut Transform, (With<Interact>, Without<Player>)>,
    children: Query<&mut Children>,
) {
    let (action, transform, mut item) = single_mut!(player_query);
    if *action == PlayerAction::Drop {
        let Some(item) = item.take() else {
            return;
        };
        if let Ok(mut vis) = vis_query.get_mut(item) {
            *vis = Visibility::Visible;
        }
        if let Ok(colliders) = children.get(item) {
            for &collider in colliders {
                commands.entity(collider).remove::<ColliderDisabled>();
            }
        }

        // for simplicities sake, set the transform of the item that is dropped to that of the player
        let mut item_transform = item_transform.get_mut(item).unwrap();
        *item_transform = *transform;
    }
}

pub fn handle_door_interaction(
    player_query: Query<&PlayerAction, With<Player>>, mut doors: Query<&mut Door>
) {
    let Ok(action) = player_query.get_single() else {
        return;
    };
    if *action != PlayerAction::OpenDoor {
        return;
    }

    for mut door in doors.iter_mut() {
        door.is_open = !door.is_open;
    }
}
