// Copyright (c) 2017, Marty Mills <daggerbot@gmail.com>
// This software is available under the terms of the zlib license.
// See COPYING.md for more information.

use dnum::Lerp;

use clamp::Clamp;

/// Gets the luminance of a non-luminance color type.
pub trait Luminance {
    fn luminance (self) -> f64;
}

/// Luminance color type.
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde_", derive(Serialize, Deserialize))]
#[repr(C)]
pub struct Lum<T> {
    pub l: T,
}

impl<T> Lum<T> {
    pub fn new (l: T) -> Lum<T> {
        Lum { l }
    }

    pub fn with_alpha (self, a: T) -> Luma<T> {
        Luma { l: self.l, a }
    }
}

impl<T> Clamp for Lum<T>
    where T: Clamp
{
    fn clamp_min () -> Lum<T> { Lum { l: T::clamp_min() } }
    fn clamp_max () -> Lum<T> { Lum { l: T::clamp_max() } }
}

impl<S, T> Lerp<T> for Lum<S>
    where S: Lerp<T>
{
    fn lerp (a: Lum<S>, b: Lum<S>, t: T) -> Lum<S> {
        Lum { l: S::lerp(a.l, b.l, t) }
    }
}

/// Luminance-alpha color type.
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde_", derive(Serialize, Deserialize))]
#[repr(C)]
pub struct Luma<T> {
    pub l: T,
    pub a: T,
}

impl<T> Luma<T> {
    pub fn drop_alpha (self) -> Lum<T> {
        Lum { l: self.l }
    }

    pub fn new (l: T, a: T) -> Luma<T> {
        Luma { l, a }
    }

    pub fn split_alpha (self) -> (Lum<T>, T) {
        (Lum { l: self.l }, self.a)
    }
}

impl<T> Clamp for Luma<T>
    where T: Clamp
{
    fn clamp_min () -> Luma<T> { Luma { l: T::clamp_min(), a: T::clamp_min() } }
    fn clamp_max () -> Luma<T> { Luma { l: T::clamp_max(), a: T::clamp_max() } }
}

impl<S, T> Lerp<T> for Luma<S>
    where S: Lerp<T>, T: Copy
{
    fn lerp (a: Luma<S>, b: Luma<S>, t: T) -> Luma<S> {
        Luma {
            l: S::lerp(a.l, b.l, t),
            a: S::lerp(a.a, b.a, t),
        }
    }
}
