use iced::Color;
use iced::color::Oklch;
use plushie_core::types::{Color as CoreColor, PlushieType};
use crate::iced_convert;
pub fn interpolate(from: Color, to: Color, t: f32) -> Color {
let from_oklch = from.into_oklch();
let to_oklch = to.into_oklch();
let l = lerp(from_oklch.l, to_oklch.l, t);
let c = lerp(from_oklch.c, to_oklch.c, t);
let a = lerp(from_oklch.a, to_oklch.a, t);
let h = hue_lerp(from_oklch, to_oklch, t);
Color::from_oklch(Oklch { l, c, h, a })
}
fn lerp(a: f32, b: f32, t: f32) -> f32 {
a + (b - a) * t
}
fn hue_lerp(from: Oklch, to: Oklch, t: f32) -> f32 {
const ACHROMATIC_THRESHOLD: f32 = 0.001;
let pi = std::f32::consts::PI;
let from_achromatic = from.c < ACHROMATIC_THRESHOLD;
let to_achromatic = to.c < ACHROMATIC_THRESHOLD;
if from_achromatic && to_achromatic {
0.0
} else if from_achromatic {
to.h
} else if to_achromatic {
from.h
} else {
let mut diff = to.h - from.h;
if diff > pi {
diff -= 2.0 * pi;
} else if diff < -pi {
diff += 2.0 * pi;
}
from.h + diff * t
}
}
pub fn parse_color(value: &serde_json::Value) -> Option<Color> {
CoreColor::wire_decode(value).map(|c| iced_convert::color(&c))
}
pub fn color_to_hex(c: Color) -> String {
let r = (c.r.clamp(0.0, 1.0) * 255.0).round() as u8;
let g = (c.g.clamp(0.0, 1.0) * 255.0).round() as u8;
let b = (c.b.clamp(0.0, 1.0) * 255.0).round() as u8;
if (c.a - 1.0).abs() < f32::EPSILON {
format!("#{r:02x}{g:02x}{b:02x}")
} else {
let a = (c.a.clamp(0.0, 1.0) * 255.0).round() as u8;
format!("#{r:02x}{g:02x}{b:02x}{a:02x}")
}
}