use rayon::iter::{IntoParallelIterator, ParallelIterator};

use crate::vec3::{Color, Vec3};

use super::util::RenderContext;

impl super::Raytracer {
	pub fn render_multithread_rayon_detached(self, ctx: RenderContext) {
		let render_id = ctx.render_id();
		std::thread::spawn(move || {
			let start = std::time::Instant::now();
			tracing::info!("Starting Render ID {render_id:#06X}");
			let terminated = (0..self.image_height)
				.into_par_iter()
				.flat_map(|y| (0..self.image_width).into_par_iter().map(move |x| (x, y)))
				.any(|(i, j)| {
					if ctx.render_id() != render_id {
						return true;
					}

					let mut pixel_color = Vec3::default();

					for _ in 0..self.samples_per_pixel {
						let ray = self.get_ray(i, j);
						pixel_color += self.ray_color(self.max_depth, &ray);
					}

					ctx.set_color(i, j, pixel_color * self.pixel_samples_scale);

					false
				});

			tracing::info!(
				"Finished Render ID {render_id:#06X} in {}s (terminated={terminated})",
				start.elapsed().as_secs_f64()
			);
		});
	}

	pub fn render_multithread_rayon(&self) -> Vec<Color> {
		(0..self.image_height)
			.into_par_iter()
			.flat_map(|y| (0..self.image_width).into_par_iter().map(move |x| (x, y)))
			.map(|(i, j)| {
				tracing::debug!("Scanlines remaining: {}", self.image_height - j);
				let mut pixel_color = Vec3::default();

				for _ in 0..self.samples_per_pixel {
					let ray = self.get_ray(i, j);
					pixel_color += self.ray_color(self.max_depth, &ray);
				}

				pixel_color * self.pixel_samples_scale
			})
			.collect()
	}

	pub fn render(&self) -> Vec<Color> {
		let mut out = Vec::with_capacity(self.image_height * self.image_width);

		for j in 0..self.image_height {
			tracing::debug!("Scanlines remaining: {}", self.image_height - j);
			for i in 0..self.image_width {
				let mut pixel_color = Color::default();

				for _ in 0..self.samples_per_pixel {
					let ray = self.get_ray(i, j);
					pixel_color += self.ray_color(self.max_depth, &ray);
				}

				out.push(pixel_color * self.pixel_samples_scale);
			}
		}

		out
	}
}
