use crate::ecs::Entity;
use crate::ecs::prefab::components::{
    NodePath, PrefabId, PrefabOverrides, TransformOverride, prefab_instance_has_overrides,
    prefab_instance_with_path, transform_override_from_transforms, transform_override_is_none,
};
use crate::ecs::world::World;
use crate::ecs::world::components::LocalTransform;

pub fn revert_instance_to_prefab(
    world: &mut World,
    entity: Entity,
    base_transform: &LocalTransform,
) -> bool {
    let Some(instance) = world.get_prefab_instance(entity) else {
        return false;
    };

    let mut new_instance = instance.clone();
    new_instance.overrides = PrefabOverrides::default();

    world.set_prefab_instance(entity, new_instance);
    world.set_local_transform(entity, *base_transform);

    true
}

pub fn break_prefab_link(world: &mut World, entity: Entity) -> bool {
    if world.get_prefab_instance(entity).is_none() {
        return false;
    }

    world.remove_prefab_instance(entity);
    true
}

pub fn detect_transform_override(
    world: &World,
    entity: Entity,
    base_transform: &LocalTransform,
) -> Option<TransformOverride> {
    let current = world.get_local_transform(entity)?;
    let override_data = transform_override_from_transforms(base_transform, current);

    if transform_override_is_none(&override_data) {
        None
    } else {
        Some(override_data)
    }
}

pub fn update_instance_overrides(
    world: &mut World,
    entity: Entity,
    base_transform: &LocalTransform,
) -> bool {
    let Some(mut instance) = world.get_prefab_instance(entity).cloned() else {
        return false;
    };

    if let Some(current) = world.get_local_transform(entity) {
        instance.overrides.transform_override =
            transform_override_from_transforms(base_transform, current);
    }

    world.set_prefab_instance(entity, instance);
    true
}

pub fn create_prefab_instance(
    world: &mut World,
    entity: Entity,
    prefab_id: PrefabId,
    node_path: NodePath,
) {
    let instance = prefab_instance_with_path(prefab_id, node_path);
    world.set_prefab_instance(entity, instance);
}

pub fn has_overrides(world: &World, entity: Entity) -> bool {
    world
        .get_prefab_instance(entity)
        .map(prefab_instance_has_overrides)
        .unwrap_or(false)
}

pub fn get_prefab_id(world: &World, entity: Entity) -> Option<PrefabId> {
    world
        .get_prefab_instance(entity)
        .map(|instance| instance.prefab_id.clone())
}
