mod imp;
use crate::coords::Mapper;
use femtovg::{renderer::OpenGl, Canvas, Path};
use femtovg::{Color, FontId, ImageFlags, ImageId, Paint};
use geo_types::{LineString, Point};
use glib::subclass::types::ObjectSubclassIsExt;
use gtk::glib;
use ndarray::{s, Array2, Axis, Zip};
use std::cell::Ref;

pub use self::imp::ForegroundConfig;

glib::wrapper! {
    pub struct ForegroundWidget(ObjectSubclass<imp::ForegroundWidget>);
}

impl Default for ForegroundWidget {
    fn default() -> Self {
        Self::new(ForegroundConfig::default())
    }
}

impl ForegroundWidget {
    pub fn new(config: ForegroundConfig) -> Self {
        let this: Self = glib::Object::new();
        let imp = this.imp();
        imp.config.replace(config);
        this
    }

    pub fn draw(&self, canvas: &mut Canvas<OpenGl>, scale: f32, dpi: i32, mapper: Ref<'_, Mapper>) {
        let canvas_width = canvas.width();
        let canvas_height = canvas.height();
        let config = self.imp().config.borrow();

        let colors = self.imp().color.borrow();
        let data = self.imp().data.borrow();

        if self.imp().image.borrow().is_none() {
            println!("rebuild image");
            let img_id = canvas
                .create_image_empty(
                    canvas_width as usize,
                    canvas_height as usize,
                    femtovg::PixelFormat::Rgb8,
                    ImageFlags::empty(),
                )
                .unwrap();
            if let Ok(v) = canvas.image_size(img_id) {
                println!("create image: {:?}", v);
                canvas.set_render_target(femtovg::RenderTarget::Image(img_id));
                let colors = self.imp().color.borrow();
                let data = self.imp().data.borrow();
                if colors.is_some() && data.is_some() {
                    for (i, c) in colors
                        .as_ref()
                        .unwrap()
                        .t()
                        .iter()
                        .zip(data.as_ref().unwrap().iter())
                    {
                        if i.is_none() {
                            continue;
                        }
                        let pts = c.points().collect::<Vec<Point>>();
                        let first_point = pts[0];
                        let mut path = Path::new();
                        path.move_to(
                            first_point.x() as f32 * v.0 as f32 + 0.8,
                            first_point.y() as f32 * v.1 as f32 + 0.8,
                        );

                        pts[1..].into_iter().for_each(|p| {
                            path.line_to(p.x() as f32 * v.0 as f32, p.y() as f32 * v.1 as f32)
                        });
                        let c = i.unwrap();
                        canvas.fill_path(&path, &Paint::color(c));
                    }
                }

                self.imp().image.replace(Some(img_id));
            }
        }

        canvas.set_render_target(femtovg::RenderTarget::Screen);

        let mut path = Path::new();
        path.rect(0.0, 0.0, canvas_width, canvas_height);

        canvas.fill_path(
            &path,
            &Paint::image(
                self.imp().image.borrow().as_ref().unwrap().to_owned(),
                0.0,
                0.0,
                canvas_width,
                canvas_height,
                0.0,
                1.0,
            ),
        );
    }

    pub(super) fn set_dims(&self, dims: (Array2<f64>, Array2<f64>)) {
        self.imp().dim1.replace(Some(dims.0));
        self.imp().dim2.replace(Some(dims.1));
    }

    pub(super) fn set_image(&self, image: ImageId) {
        self.imp().image.replace(Some(image));
    }

    pub fn set_colors(&self, colors: Array2<Option<Color>>) {
        self.imp().color.replace(Some(colors));
    }

    pub fn set_data(&self, data: Array2<LineString>) {
        self.imp().data.replace(Some(data));
    }
}

// let levels: Vec<i8> = vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65];
//         let colors = vec![
//             Color::rgb(0, 172, 164),
//             Color::rgb(192, 192, 254),
//             Color::rgb(122, 114, 238),
//             Color::rgb(30, 38, 208),
//             Color::rgb(166, 252, 168),
//             Color::rgb(0, 234, 0),
//             Color::rgb(16, 146, 26),
//             Color::rgb(252, 244, 100),
//             Color::rgb(200, 200, 2),
//             Color::rgb(140, 140, 0),
//             Color::rgb(254, 172, 172),
//             Color::rgb(254, 100, 92),
//             Color::rgb(238, 2, 48),
//             Color::rgb(212, 142, 254),
//             Color::rgb(170, 36, 250),
//         ];

// Zip::from(c).and(d).and(e).for_each(|lon, lat, d| {
//     if *d < -5 || *d > 70 {
//         return;
//     }

//     let left_bottom = mapper.map((*lon, *lat)).unwrap();
//     let right_top = mapper.map((lon + 0.005, lat + 0.005)).unwrap();

//     // let (lon1, lat1) = (
//     //     left_bottom.0 * canvas_width as f64,
//     //     left_bottom.1 * canvas_height as f64,
//     // );

//     let color = get(&levels, &colors, *d);
//     //
//     // let (lon2, lat2) = (
//     //     right_top.0 * canvas_width as f64,
//     //     right_top.1 * canvas_height as f64,
//     // );

//     let line_string: LineString = vec![
//         (left_bottom.0, left_bottom.1),
//         (right_top.0, left_bottom.1),
//         (right_top.0, right_top.1),
//         (left_bottom.0, right_top.1),
//         (left_bottom.0, left_bottom.1),
//     ]
//     .into();

//     // let line_string: LineString = vec![
//     //     (lon1, lat1),
//     //     (lon2, lat1),
//     //     (lon2, lat2),
//     //     (lon1, lat2),
//     //     (lon1, lat1),
//     // ]
//     // .into();

//     let res = mapper.ring_map(&line_string).unwrap();

//     let mut path = Path::new();

//     path.move_to(
//         left_bottom.0 as f32 * canvas_width,
//         left_bottom.1 as f32 * canvas_height,
//     );

//     for p in line_string.points() {
//         // path.move_to(p.x() as f32 * canvas_width, p.y() as f32 * canvas_height);
//         path.line_to(p.x() as f32 * canvas_width, p.y() as f32 * canvas_height);
//     }
//     canvas.fill_path(&path, &Paint::color(color));
// });
