#![allow(unused)]

use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};

use data::math_def::{Vector3, VECTOR3_ZERO};
use parking_lot::Mutex;

use crate::entity::Entity;

use super::Scene;

#[derive(Default)]
pub struct RegionBase {
    pub entity_table: HashMap<u32, Arc<Mutex<dyn Entity>>>,
}

pub enum RegionShape {
    Sphere,
    Cubic,
    Cylinder,
    Polygon,
}

pub enum Region {
    Cubic(RegionBase, Vector3, Vector3),
}

impl Region {
    pub fn new_cubic(pos: Vector3, size: Vector3) -> Region {
        Region::Cubic(RegionBase::default(), pos, size)
    }

    pub fn get_region_shape(&self) -> RegionShape {
        match self {
            //Self::Sphere(..) => RegionShape::Sphere,
            Self::Cubic(..) => RegionShape::Cubic,
        }
    }

    pub fn add_entity(&mut self, entity_ptr: Arc<Mutex<dyn Entity>>) {
        let entity_id = entity_ptr.lock().entity_id();
        self.base_mut().entity_table.insert(entity_id, entity_ptr);

        // TODO: group events
    }

    pub fn is_in_region(&self, pos: &Vector3) -> bool {
        match self {
            Self::Cubic(_, position, size) => {
                if pos.x < (position.x as f32 - (size.x as f32 / 2.0))
                    || ((size.x as f32 / 2.0) + position.x as f32) < pos.x as f32
                {
                    return false;
                }

                if pos.y < (position.y as f32 - (size.y as f32 / 2.0))
                    || ((size.y as f32 / 2.0) + position.y as f32) < pos.y as f32
                {
                    return false;
                }

                pos.z < (position.z as f32 - (size.z as f32 / 2.0))
                    || ((size.z as f32 / 2.0) + position.z as f32) < pos.z as f32
            }
        }
    }

    fn base(&self) -> &RegionBase {
        match self {
            //Self::Sphere(base) => &base,
            Self::Cubic(base, ..) => &base,
        }
    }

    fn base_mut(&mut self) -> &mut RegionBase {
        match self {
            //Self::Sphere(base) => &mut base,
            Self::Cubic(base, ..) => base,
        }
    }
}

impl Entity for Region {
    fn get_entity_type(&self) -> proto::ProtEntityType {
        proto::ProtEntityType::ProtEntityRegion
    }

    fn get_group_id(&self) -> u32 {
        0 // todo?
    }

    fn entity_id(&self) -> u32 {
        0
    }

    fn set_entity_id(&mut self, _id: u32) {}

    fn position(&self) -> &data::math_def::Vector3 {
        match self {
            Self::Cubic(_, pos, ..) => pos,
        }
    }

    fn rotation(&self) -> &data::math_def::Vector3 {
        &VECTOR3_ZERO
    }

    fn set_position(&mut self, pos: data::math_def::Vector3) {
        match self {
            Self::Cubic(_, p, ..) => *p = pos,
        };
    }

    fn set_rotation(&mut self, _rot: data::math_def::Vector3) {}

    fn get_owner_player(&self) -> Option<Rc<crate::player::Player>> {
        None
    }
}
