use femtovg::{renderer::OpenGl, Canvas, Paint};
use num_traits::{Num, NumOps};
use std::sync::Arc;
use std::thread::spawn;
use std::{os::unix::thread, path::Path};

use crate::render::cms::CMS;
use crate::render::{LayerImpl, Target};
use crate::OFFSCREEN;
use crate::{
    data::{AsyncDataLoader, DataLoader, Radar2d},
    render::{Layer, Render},
};

use super::{
    color_mapper::ColorMapper,
    grid_field_renderer::{GridFieldRenderer, GridLayerImpl},
};

impl Layer {
    pub fn grid_render_layer<T, CMAP>(data: Radar2d<T>, layer_name: String, color_map: CMAP) -> Self
    where
        T: std::fmt::Debug + Num + NumOps + PartialOrd + Copy + Clone + 'static + Send + Sync,
        CMAP: ColorMapper<T> + 'static,
    {
        Self::new(
            true,
            |s, render, _| {
                if let Some(target) = s.render_target() {
                    let mut c = render.get_canvas();
                    let c = c.as_mut().unwrap();
                    if let Ok(_) = c.image_size(target.target) {
                        let (x, y) = target.size(&render);
                        let (ox, oy) = target.origin(&render);
                        let painter = Paint::image(target.target, ox, oy, x, y, 0.0, 1.0);
                        let mut path = femtovg::Path::new();
                        path.rect(ox, oy, x, y);
                        c.fill_path(&path, &painter);
                    }
                }
            },
            layer_name,
            Some(
                |s_imp: Box<dyn LayerImpl>, c: &mut Canvas<OpenGl>, cms: CMS| async move {
                    if let Some(renderer) = s.as_ref() {
                        let img = renderer.draw(render.clone()).unwrap();
                        if let Ok(_) = c.image_size(img.target) {
                            let (x, y) = img.size(&render);
                            let (ox, oy) = img.origin(&render);
                            println!("{} {} {} {}", x, y, ox, oy);
                            let painter = Paint::image(img.target, ox, oy, x, y, 0.0, 1.0);
                            let mut path = femtovg::Path::new();
                            path.rect(ox, oy, x, y);
                            s.set_render_target(img);
                            c.fill_path(&path, &painter);
                        }
                    }
                },
            ),
            Some(GridLayerImpl::new(GridFieldRenderer::new(color_map), data)),
        )
    }

    pub fn grid_render_layer_with_path<T, CMAP, LOADER>(
        path: impl AsRef<Path>,
        layer_name: String,
        loader: LOADER,
        color_map: CMAP,
    ) -> Self
    where
        T: Num + NumOps + PartialOrd + Copy + Clone + 'static + std::fmt::Debug + Sync + Send,
        CMAP: ColorMapper<T> + 'static,
        LOADER: DataLoader<T, Radar2d<T>>,
    {
        let data = loader.load(path).unwrap();
        self::Layer::grid_render_layer(data, layer_name, color_map)
    }

    pub async fn grid_render_layer_with_path_async<T, CMAP, LOADER>(
        path: impl AsRef<Path> + Send,
        layer_name: String,
        loader: LOADER,
        color_map: CMAP,
    ) -> Self
    where
        T: Num + NumOps + PartialOrd + Copy + Clone + 'static + std::fmt::Debug + Send + Sync,
        CMAP: ColorMapper<T> + 'static,
        LOADER: AsyncDataLoader<T, Radar2d<T>>,
    {
        let data = loader.load(path).await.unwrap();
        self::Layer::grid_render_layer(data, layer_name, color_map)
    }
}
