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

use data::math_def::Coordinate;
use proto::ProtEntityType;

use crate::entity::Entity;

use super::{grid::Grid, region::Region, VisionLevelType};

#[allow(unused)]
pub struct GridMgr {
    pub range_type: VisionLevelType,
    pub length: u32,
    pub width: u32,
    pub sight_radius: u32,
    pub grid_map: HashMap<(i32, i32), Grid>,
}

impl GridMgr {
    pub fn get_grid(&mut self, x: i32, y: i32) -> &mut Grid {
        self.grid_map.entry((x, y)).or_insert_with(Grid::default)
    }

    pub fn place_entity(
        &mut self,
        entity: Rc<RefCell<dyn Entity>>,
        coordinate: Coordinate,
    ) -> Result<Vec<Rc<RefCell<dyn Entity>>>, ()> {
        let entity_type = {
            let entity = entity.borrow();
            entity.get_entity_type()
        };

        let grid = self.get_grid(coordinate.x, coordinate.y);
        if entity_type == ProtEntityType::ProtEntityRegion {
            tracing::error!("GridMgr::place_entity shouldn't be used for Region entity");
            return Err(());
        } else {
            grid.add_entity(entity);
        }

        Ok(grid.get_all_entity())
    }

    pub fn remove_entity(&mut self, entity: &Rc<RefCell<dyn Entity>>, coordinate: Coordinate) {
        let grid = self.get_grid(coordinate.x, coordinate.y);
        grid.del_entity(entity);
    }

    #[allow(dead_code)]
    pub fn place_region(&mut self, region: Region, coordinate: Coordinate) -> Result<(), ()> {
        let grid = self.get_grid(coordinate.x, coordinate.y);
        grid.add_region(region);

        Ok(())
    }
}
