pub mod collections;
pub mod colormap;
mod colormesh;
pub mod font;
pub mod hello;
pub mod ppi;
pub mod threed;
pub mod tools;
pub mod transforms;
pub mod ty;
use crate::{components::Program, errors::*};

use glow::{NativeBuffer, NativeVertexArray};
use ppi::PPIConfig;

pub trait Graphics: AttaWithBuffer {
    fn draw(&self, gl: &glow::Context, count: i32) -> Result<()>;

    fn compile(&mut self, gl: &glow::Context) -> Result<()>;

    fn destroy(&mut self, gl: &glow::Context) -> Result<()>;

    fn program_ref(&self) -> &Program;

    fn program_mut(&mut self) -> &mut Program;

    fn mount(&mut self, gl: &glow::Context) -> Result<()>;

    fn unmount(&mut self, gl: &glow::Context) -> Result<()>;

    fn set_config(&mut self, gl: &glow::Context, config: Option<&Config>) -> Result<()>;
}

pub trait AttaWithProgram {
    fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()>;
}

pub trait AttaWithBuffer {
    type Data;

    fn bake(&self, data: &Self::Data) -> Result<(Vec<f32>, Option<Vec<u32>>, i32)>;
    fn init(&self, gl: &glow::Context) -> (NativeVertexArray, NativeBuffer, Option<NativeBuffer>);
}

macro_rules! config_for_everyitem {
    ($({$conf:ty => $name:tt},)+) => {
        $(
            impl From<$conf> for Config {
                fn from(value: $conf) -> Self {
                    Self::$name(value)
                }
            }
        )+

    };
}

#[derive(Debug, Clone)]
pub enum Config {
    PPI(PPIConfig),
}

config_for_everyitem!({PPIConfig => PPI},);

pub trait AttachWithMouse {
    fn attach_with_mouse(&mut self, state: &MouseState);
}

#[derive(Debug, Clone)]
pub enum MouseState {
    Drag { from: [f32; 2], delta: [f32; 2] },
}
