use image::RgbImage;

use crate::texture::Texture;
use crate::vec3::Vec3;

#[derive(Debug)]
pub struct ImageTexture {
    img: RgbImage,
    width: f32,
    height: f32,
}

impl ImageTexture {
    pub fn new(img: RgbImage) -> ImageTexture {
        let (w, h) = img.dimensions();
        ImageTexture {
            img,
            width: f32::from(w.min(64000) as u16),
            height: f32::from(h.min(64000) as u16),
        }
    }
}

impl Texture for ImageTexture {
    fn value(&self, u: f32, v: f32, _p: Vec3) -> Vec3 {
        // Wrap texcoords by default.
        let x = (u % 1. * (self.width - 1.)) as u32;
        let y = ((1. - v % 1.) * (self.height - 1.)) as u32;
        if x >= self.width as u32 {
            panic!(
                "u {} v {} x {} y {} w {} h {}",
                u, v, x, y, self.width, self.height
            );
        }
        if y >= self.height as u32 {
            panic!(
                "u {} v {} x {} y {} w {} h {}",
                u, v, x, y, self.width, self.height
            );
        }
        let pixel = self.img.get_pixel(x, y);
        Vec3::new(
            f32::from(pixel[0]) / 255.,
            f32::from(pixel[1]) / 255.,
            f32::from(pixel[2]) / 255.,
        )
    }
}
