use geo_types::LineString;

use crate::coords::Mapper;

pub struct CMS {
    mapper: Mapper,
    window_size: (f32, f32),
    bounds: (f64, f64, f64, f64),
}

unsafe impl Send for CMS {}
unsafe impl Sync for CMS {}

impl CMS {
    pub fn new(mapper: Mapper, window_size: (f32, f32)) -> Self {
        let bounds = mapper.get_bounds();
        Self {
            mapper,
            window_size,
            bounds,
        }
    }

    pub fn map(&self, loc: (f64, f64)) -> Option<(f32, f32)> {
        self.mapper.map(loc).ok().map(|(x, y)| {
            // println!("x: {}, y: {}", x, y);
            let (w, h) = self.window_size;
            let (w, h) = (w as f64, h as f64);
            let (x, y) = (x - self.bounds.0, y - self.bounds.2);
            let (x, y) = (
                x / (self.bounds.1 - self.bounds.0),
                1.0 - y / (self.bounds.3 - self.bounds.2),
            );
            let (x, y) = (x * w, y * h);
            (x as f32, y as f32)
        })
    }

    pub fn ring_map(&self, line: &LineString) -> Option<LineString<f32>> {
        Some(
            line.points()
                .into_iter()
                .map(|p| self.map((p.x(), p.y())).unwrap())
                .collect::<Vec<_>>()
                .into(),
        )
    }
}
