use core::time::Duration;

use serde::{Deserialize, Serialize};

#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum Easing {
    Standard,
    Accelerate,
    Decelerate,
    Linear,
}

impl Easing {
    #[must_use]
    pub const fn cubic_bezier(self) -> [f32; 4] {
        match self {
            Self::Standard => [0.2, 0.0, 0.0, 1.0],
            Self::Accelerate => [0.3, 0.0, 1.0, 1.0],
            Self::Decelerate => [0.0, 0.0, 0.0, 1.0],
            Self::Linear => [0.0, 0.0, 1.0, 1.0],
        }
    }
}

impl core::fmt::Display for Easing {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let name = match self {
            Self::Standard => "standard",
            Self::Accelerate => "accelerate",
            Self::Decelerate => "decelerate",
            Self::Linear => "linear",
        };
        f.write_str(name)
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct MotionToken {
    pub duration: Duration,
    pub easing: Easing,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Motion {
    pub fast: MotionToken,
    pub quick: MotionToken,
    pub normal: MotionToken,
    pub relaxed: MotionToken,
    pub slow: MotionToken,
    pub glacial: MotionToken,
}

impl Motion {
    pub const STANDARD: Self = Self {
        fast: MotionToken {
            duration: Duration::from_millis(80),
            easing: Easing::Standard,
        },
        quick: MotionToken {
            duration: Duration::from_millis(120),
            easing: Easing::Standard,
        },
        normal: MotionToken {
            duration: Duration::from_millis(180),
            easing: Easing::Standard,
        },
        relaxed: MotionToken {
            duration: Duration::from_millis(260),
            easing: Easing::Decelerate,
        },
        slow: MotionToken {
            duration: Duration::from_millis(400),
            easing: Easing::Decelerate,
        },
        glacial: MotionToken {
            duration: Duration::from_millis(700),
            easing: Easing::Decelerate,
        },
    };
}
