use image;

pub struct Setting {
    alpha: bool,
    color: bool,
    pub width_factor: u32,
    pub height_factor: u32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

impl Setting {
    pub fn new(in_path: &str, color: bool) -> Self {
        let in_img = image::open(in_path).unwrap();
        Self {
            alpha: in_img.color().has_alpha(),
            color,
            width_factor: in_img.width() / 5,
            height_factor: in_img.height() / 5,
            width: in_img.width(),
            height: in_img.height(),
            bytes: in_img.into_bytes(),
        }
    }

    pub fn coef(&self) -> u32 {
        if self.alpha {
            4
        } else {
            3
        }
    }

    pub fn light_color(&self, image: &[u8]) -> [u8; 4] {
        if self.color {
            self.get_light_color(image)
        } else if self.alpha {
            self.light_color_with_alpha(image)
        } else {
            self.default_light_color()
        }
    }

    fn get_light_color(&self, image: &[u8]) -> [u8; 4] {
        let mut red = 0;
        let mut green = 0;
        let mut blue = 0;
        let mut alpha = 255;
        for x in 0..25 {
            let a = image[x * 3];
            let b = image[x * 3 + 1];
            let c = image[x * 3 + 2];
            if red < a && green < b && blue < c {
                red = a;
                green = b;
                blue = c;
                if self.alpha {
                    alpha = image[x * 3 + 3];
                }
            }
        }
        [red, green, blue, alpha]
    }

    fn light_color_with_alpha(&self, image: &[u8]) -> [u8; 4] {
        let mut alpha = 0;
        for x in 0..25 {
            let d = image[x * 3 + 3];
            if d > alpha {
                alpha = d;
            }
        }
        [255, 255, 255, alpha]
    }

    fn default_light_color(&self) -> [u8; 4] {
        [255, 255, 255, 255]
    }

    pub fn dark_color(&self, image: &[u8]) -> [u8; 4] {
        if self.color {
            self.get_dark_color(image)
        } else if self.alpha {
            self.dark_color_with_alpha(image)
        } else {
            self.default_dark_color()
        }
    }

    fn get_dark_color(&self, image: &[u8]) -> [u8; 4] {
        let mut red = 255;
        let mut green = 255;
        let mut blue = 255;
        let mut alpha = 255;
        for x in 0..25 {
            let a = image[x * 3];
            let b = image[x * 3 + 1];
            let c = image[x * 3 + 2];
            if red > a && green > b && blue > c {
                red = a;
                green = b;
                blue = c;
                if self.alpha {
                    alpha = image[x * 3 + 3];
                }
            }
        }
        [red, green, blue, alpha]
    }

    fn dark_color_with_alpha(&self, image: &[u8]) -> [u8; 4] {
        let mut alpha = 0;
        for x in 0..25 {
            let d = image[x * 3 + 3];
            if d > alpha {
                alpha = d;
            }
        }
        [0, 0, 0, alpha]
    }

    fn default_dark_color(&self) -> [u8; 4] {
        [0, 0, 0, 255]
    }

    pub fn get_level(&self, image: &[u8]) -> u32 {
        let average_limunance = self.get_average_limunance(image);
        let float_level = average_limunance / 25.50;
        float_level.trunc() as u32
    }

    fn get_average_limunance(&self, image: &[u8]) -> f32 {
        let mut sum = 0.00;

        for x in 0..25 {
            let red = f32::from(image[x * 3]);
            let green = f32::from(image[x * 3 + 1]);
            let blue = f32::from(image[x * 3 + 2]);
            let limunance = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
            sum = sum + limunance;
        }
        sum / 25.00
    }
}
