use super::*;

#[derive(Debug)]
pub(super) struct FloatCheckerboardTexture2d {
    pub(super) mapping: UVMapping,
    pub(super) tex: [Either<Float, Arc<dyn Pbrt2dFloatTexture>>; 2],
}

impl Pbrt2dFloatTexture for FloatCheckerboardTexture2d {
    fn get(&self, u: Float, v: Float) -> Float {
        let (u, v) = self.mapping.map(u, v);

        let even = if u >= 0.0 {
            u.fract() >= 0.5
        } else {
            u.fract() >= -0.5
        } ^ if v >= 0.0 {
            v.fract() >= 0.5
        } else {
            v.fract() >= -0.5
        };

        match &self.tex[even as usize] {
            Either::A(v) => *v,
            Either::B(t) => t.get(u, v),
        }
    }
}

impl PbrtTexture for FloatCheckerboardTexture2d {
    fn get_2d_float_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt2dFloatTexture>> {
        Ok(self)
    }

    fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt2dSpectrumTexture>> {
        Err(miette!("Unable to use this texture as a spectrum texture"))
    }

    fn get_dimension(&self) -> TextureDimension {
        TextureDimension::D2
    }
}
#[derive(Debug)]
pub(super) struct SpectrumCheckerboardTexture2d {
    pub(super) mapping: UVMapping,
    pub(super) tex: [Either<Color, Arc<dyn Pbrt2dSpectrumTexture>>; 2],
}

impl Pbrt2dSpectrumTexture for SpectrumCheckerboardTexture2d {
    fn get(&self, u: Float, v: Float) -> Color {
        let (u, v) = self.mapping.map(u, v);
        let even = (u.floor() as i64 + v.floor() as i64) % 2 == 0;

        match &self.tex[even as usize] {
            Either::A(v) => *v,
            Either::B(t) => t.get(u, v),
        }
    }
}

impl PbrtTexture for SpectrumCheckerboardTexture2d {
    fn get_2d_float_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt2dFloatTexture>> {
        Err(miette!("Unable to use this texture as a float texture"))
    }

    fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt2dSpectrumTexture>> {
        Ok(self)
    }

    fn get_dimension(&self) -> TextureDimension {
        TextureDimension::D2
    }
}
