// Copyright Marcus Del Favero 2025
// Licensed under the GNU AGPLv3 with an exception, see `README.md` for details
use super::inkscape;
use super::image::Image;
use super::layer::{Layer, Kernel};
use crate::utils;

use png::ColorType;
use glam::{IVec2, Vec3, Vec4};

pub fn generate() {
	const INPUT: &str = "data/bullet.svg";
	const INTERMEDIATE: &str = "/tmp/bullet.png";
	const OUTPUT: &str = "../data/textures/ammo_status.png";

	const SIZE: usize = 96;
	const BULLET_SIZE: usize = 24;

	if !utils::newer(INPUT, OUTPUT) { return; }

	inkscape::gen_image(INPUT, INTERMEDIATE, BULLET_SIZE, BULLET_SIZE, ColorType::Rgba);
	let bullet_image = Image::load(INTERMEDIATE, ColorType::Rgba);
	assert!(bullet_image.width == BULLET_SIZE && bullet_image.height == BULLET_SIZE);

	let mut layer = Layer::<Vec4>::new(SIZE, SIZE, Vec3::ZERO.extend(0.5));
	let mut tmp_layer = Layer::<Vec4>::new(SIZE, SIZE, Vec4::ZERO);
	let bullet_layer = Layer::from(bullet_image);

	let kernel = Layer::gaussian_blur_kernel(5.0);

	for pos in [[36, 16], [46, 36], [26, 36], [56, 56], [36, 56], [16, 56]].into_iter().map(IVec2::from_array) {
		add_bullet(&mut tmp_layer, &bullet_layer, &kernel, pos);
		layer.add(&tmp_layer, IVec2::ZERO);
	}

	let mut output = Image::from(layer);
	add_border(&mut output);
	output.save(OUTPUT, ColorType::Rgba);
}

/**
 * Sets the `output` layer to be containing a bullet, with a blur underneath
 * it. All contents of `output` are cleared.
 */
fn add_bullet(output: &mut Layer<Vec4>, bullet: &Layer<Vec4>, kernel: &Kernel, pos: IVec2) {
	output.clear();
	output.add(bullet, pos);
	output.blacken();
	output.gaussian_blur(kernel);
	output.add(bullet, pos);
}

fn add_border(output: &mut Image) {
	const OUTER: u8 = 0x7f;
	const INNER: u8 = 0x5f;

	assert_eq!(output.width, output.height);
	let size = output.width;

	let borders = [OUTER, OUTER, INNER, INNER];

	for (i, colour) in borders.into_iter().enumerate() {
		for j in i..size - i {
			grey_pixel(output, j, i, colour);
			grey_pixel(output, j, output.height - i - 1, colour);
			grey_pixel(output, i, j, colour);
			grey_pixel(output, output.width - i - 1, j, colour);
		}
	}
}

fn grey_pixel(image: &mut Image, x: usize, y: usize, colour: u8) {
	let i = (x + y * image.width) * 4;
	image.pixels[i    ] = colour;
	image.pixels[i + 1] = colour;
	image.pixels[i + 2] = colour;
	image.pixels[i + 3] = 0xff;
}
