use guarded::guarded_unwrap;
use palette::{Mix, IntoColor};
use rbx_types::Variant;
use rbx_types_ops::Lerp;
use crate::parser::Datatype;
use super::coerce_datatype_to_f32;
macro_rules! op_match_between_two_variants {
($method_name:ident, $from:expr, $to:expr, $time:expr, [$($name:ident),*]) => {
match ($from, $to) {
(Datatype::Oklab(from), Datatype::Oklab(to)) => Datatype::Oklab(from.mix(*to, $time)),
(Datatype::Oklab(from), Datatype::Oklch(to)) => Datatype::Oklab(from.mix((*to).into_color(), $time)),
(Datatype::Oklch(from), Datatype::Oklch(to)) => Datatype::Oklch(from.mix(*to, $time)),
(Datatype::Oklch(from), Datatype::Oklab(to)) => Datatype::Oklch(from.mix((*to).into_color(), $time)),
_ => match ($from.clone().coerce_to_variant(None), $to.clone().coerce_to_variant(None)) {
(Some(from), Some(to)) => match (&from, &to) {
$(
(Variant::$name(from), Variant::$name(to)) => {
Datatype::Variant(Variant::$name(from.$method_name(to, $time)))
}
)*
_ => return Datatype::Variant(from)
}
(Some(from), None) => Datatype::Variant(from),
_ => Datatype::None
}
}
};
}
pub fn lerp_annotation(datatypes: &Vec<Datatype>) -> Datatype {
let from = guarded_unwrap!(datatypes.get(0), return Datatype::None);
let to = guarded_unwrap!(datatypes.get(1), return from.clone());
let time = coerce_datatype_to_f32(datatypes.get(2), 0.5);
op_match_between_two_variants!(
lerp, from, to, time, [
Float32, UDim, UDim2, Rect, Vector2, Vector2int16,
Vector3, Vector3int16, CFrame, Color3, Color3uint8
]
)
}