pub mod parser;
pub mod default_palettes;

pub use ordered_float::OrderedFloat;

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Color {
    pub red: u8,
    pub green: u8,
    pub blue: u8,
    pub alpha: u8
}

pub type Palette = Vec<((OrderedFloat<f64>, OrderedFloat<f64>), (Color, Color))>;

#[macro_export]
macro_rules! c {
    ($r:expr,$g:expr,$b:expr) => {
        crate::Color { red: $r, green: $g, blue: $b, alpha: 255 }
    };
    ($r:expr,$g:expr,$b:expr,$a:expr) => {
        crate::Color { red: $r, green: $g, blue: $b, alpha: $a }
    };
}

#[macro_export]
macro_rules! r {
    ($f:expr,$t:expr) => {
        (crate::OrderedFloat($f), crate::OrderedFloat($t))
    };
}

pub trait ColorPalette {
    fn colorize(&self, at: f64) -> Color;
}
impl ColorPalette for Palette {
    fn colorize(&self, at: f64) -> Color {
        for (raw_range, color_range) in self {
            let range = *raw_range.0 .. *raw_range.1;
            if range.contains(&at) {

                let mapped_end = *raw_range.1 - *raw_range.0;
                let mapped_point = at - *raw_range.0;
                let t = mapped_point / mapped_end;

                let color_start = color_range.0;
                let color_end = color_range.1;

                return lerp_color(color_start, color_end, t);
            }
        }
        Color {
            red: 0,
            green: 0,
            blue: 0,
            alpha: 0
        }
    }
}

fn lerp(p0: f64, p1: f64, t: f64) -> f64 {
    p0 + t * (p1 - p0)
}
fn lerp_color(c0: Color, c1: Color, t: f64) -> Color {
    Color {
        red: lerp(c0.red as f64, c1.red as f64, t) as u8,
        green: lerp(c0.green as f64, c1.green as f64, t) as u8,
        blue: lerp(c0.blue as f64, c1.blue as f64, t) as u8,
        alpha: lerp(c0.alpha as f64, c1.alpha as f64, t) as u8
    }
}
