// Copyright 2026 Gabriel Bjørnager Jensen.
//
// This file is part of LOOKLOOK.
//
// LOOKLOOK is free software: you can redistribute
// it and/or modify it under the terms of the GNU
// Affero General Public License as published by
// the Free Software Foundation, either version 3
// of the License, or (at your option) any later
// version.
//
// LOOKLOOK is distributed in the hope that it will
// be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Af-
// fero General Public License along with LOOKLOOK.
// If not, see <https://www.gnu.org/licenses/>.

//! The [`Looklook`] type.

use crate::mode::{ColourDepth, FrameResolution, Mode, ModeVideo};
use crate::render::Render;
use crate::synth::Synth;

/// A LOOKLOOK instance.
pub struct Looklook(());

impl Looklook {
	/// The major version of LOOKLOOK.
	pub const VERSION_MAJOR: u32 = 0;

	/// The minor version of LOOKLOOK.
	pub const VERSION_MINOR: u32 = 2;

	/// The patch version of LOOKLOOK.
	pub const VERSION_PATCH: u32 = 0;

	/// Constructs a new LOOKLOOK instance.
	#[must_use]
	pub const fn new() -> Self {
		Self(())
	}

	/// Runs LOOKLOOK.
	pub fn run(self) {
		const VIDEO_WIDTH: FrameResolution = FrameResolution::new(512).unwrap();

		let mode: Mode = ModeVideo {
			width:        VIDEO_WIDTH,
			height:       VIDEO_WIDTH,
			colour_depth: const { ColourDepth::new(2).unwrap() },
			frame_count:  1,
			..Default::default()
		}.into();

		let mut render = Render::new();
		render.configure(&mode);

		let series: Vec<Synth> = [
			Synth::new(
				|mut index| {
					let colour_index = index % 3;

					// Map from colour to greyscale.
					index /= 3;

					let y = index / u32::from(VIDEO_WIDTH.as_u16());
					let x = index % u32::from(VIDEO_WIDTH.as_u16());

					match colour_index {
						// Red.
						0 => {
							u32::MAX - (u32::MAX / u32::from(VIDEO_WIDTH.as_u16())).saturating_mul(x)
						}

						// Green.
						1 => {
							(u32::MAX / u32::from(VIDEO_WIDTH.as_u16())).saturating_mul(y)
						}

						// Green.
						2 => {
							(u32::MAX / u32::from(VIDEO_WIDTH.as_u16())).saturating_mul(x)
						}

						_ => {
							unreachable!();
						}
					}
				},
			),
		].into();

		render.render(&series);
		render.encode(&mode);

		render.dump_at(&mode, "output.png").unwrap();
	}
}

impl Default for Looklook {
	#[inline]
	fn default() -> Self {
		Self::new()
	}
}
