use glow::HasContext;

use crate::{
    components::{CodeType, Program, Shader},
    graphics::transforms::{
        polar::Polar, position::Position, trackball::Trackball, viewport::Viewport, Transform,
    },
};

pub struct PPI {
    transform: Trackball,
    program: Program,
}

impl PPI {
    pub fn new(version: &'static str) -> Self {
        let trackball = Trackball::new().unwrap();
        let projection = Polar::new().unwrap();
        let position = Position::new().unwrap();

        let transform = trackball.chain(projection.chain(position));

        let vertex = Shader::new(
            glow::VERTEX_SHADER,
            CodeType::<&'static str>::Path("agg-fast-path.vert".into()),
        )
        .unwrap();

        let fragment = Shader::new(
            glow::FRAGMENT_SHADER,
            CodeType::<&'static str>::Path("agg-fast-path.frag".into()),
        )
        .unwrap();

        let mut program = Program::new(vertex, fragment, None, version);

        let viewport = Viewport::new().unwrap();

        program.set_transform(&transform);

        program.set_viewport(&viewport);

        Self { transform, program }
    }

    pub fn compile(&mut self, gl: &glow::Context) {
        self.program.compile(gl);
    }

    pub fn program(&self) -> &Program {
        &self.program
    }

    pub fn native_program(&self) -> Option<<glow::Context as HasContext>::Program> {
        self.program.native_program
    }
}

mod test {
    use super::*;

    #[test]
    fn test_ppi() {
        let ppi = PPI::new("450");

        println!("{}", ppi.program.vertex());
    }
}
