pub struct RGBA {
    pub r: u8,
    pub g: u8,
    pub b: u8,
    pub a: u8,
}

impl RGBA {
    const WHITE: RGBA = RGBA {
        r: 0xFF,
        g: 0xFF,
        b: 0xFF,
        a: 0xFF,
    };

    const BLACK: RGBA = RGBA {
        r: 0,
        g: 0,
        b: 0,
        a: 0xFF,
    };

    const CLEAR: RGBA = RGBA {
        r: 0,
        g: 0,
        b: 0,
        a: 0,
    };

    pub fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
        RGBA { r, g, b, a }
    }

    pub fn rgb(r: u8, g: u8, b: u8) -> Self {
        Self::rgba(r, g, b, 255)
    }
}

impl From<RGBA> for i32 {
    fn from(value: RGBA) -> Self {
        i32::from_be_bytes(value.into())
    }
}

impl From<i32> for RGBA {
    fn from(value: i32) -> Self {
        i32::to_be_bytes(value).into()
    }
}

impl From<RGBA> for u32 {
    fn from(value: RGBA) -> Self {
        u32::from_be_bytes(value.into())
    }
}

impl From<u32> for RGBA {
    fn from(value: u32) -> Self {
        u32::to_be_bytes(value).into()
    }
}

impl From<[u8; 3]> for RGBA {
    fn from(value: [u8; 3]) -> Self {
        Self::rgb(value[0], value[1], value[2])
    }
}

impl From<RGBA> for [u8; 3] {
    fn from(value: RGBA) -> Self {
        [value.r, value.g, value.b]
    }
}

impl From<[u8; 4]> for RGBA {
    fn from(value: [u8; 4]) -> Self {
        Self::rgba(value[0], value[1], value[2], value[3])
    }
}

impl From<RGBA> for [u8; 4] {
    fn from(value: RGBA) -> Self {
        [value.r, value.g, value.b, value.a]
    }
}

impl From<(u8, u8, u8)> for RGBA {
    fn from(value: (u8, u8, u8)) -> Self {
        Self::rgb(value.0, value.1, value.2)
    }
}

impl From<RGBA> for (u8, u8, u8) {
    fn from(value: RGBA) -> Self {
        (value.r, value.g, value.b)
    }
}

impl From<(u8, u8, u8, u8)> for RGBA {
    fn from(value: (u8, u8, u8, u8)) -> Self {
        Self::rgba(value.0, value.1, value.2, value.3)
    }
}

impl From<RGBA> for (u8, u8, u8, u8) {
    fn from(value: RGBA) -> Self {
        (value.r, value.g, value.b, value.a)
    }
}

pub struct ColorPair {
    pub bg: RGBA,
    pub fg: RGBA,
}

impl ColorPair {
    pub fn new(bg: RGBA, fg: RGBA) -> Self {
        Self { bg, fg }
    }
}

impl<T1: Into<RGBA>, T2: Into<RGBA>> From<(T1, T2)> for ColorPair {
    fn from(value: (T1, T2)) -> Self {
        Self {
            bg: value.0.into(),
            fg: value.1.into(),
        }
    }
}