// Copyright Marcus Del Favero 2025
// Licensed under the GNU AGPLv3 with an exception, see `README.md` for details
use std::{io::BufWriter, fs::File, path::{Path, PathBuf}};

use png::{Encoder, ColorType, BitDepth};

use super::{config::{self, blocks::BlockConfig}, super::multiplayer::config::Config as MultiplayerConfig};
#[cfg(feature = "client")] use super::super::level::config::Config as LevelConfig;

pub fn save_blocks(config_path: PathBuf, output_path: &Path, level: bool) -> Result<(), String> {
	let blocks = get_config(&config_path, level)?;

	let bmap = blocks.generate_map(config_path).map_err(|err| format!("cannot generate config: {err}"))?;
	let file = File::create(output_path).map_err(|err| format!("cannot open \"{}\" for saving image: {err}", output_path.display()))?;

	let mut encoder = Encoder::new(BufWriter::new(file), blocks.grid_size.x, blocks.grid_size.y);
	encoder.set_color(ColorType::Grayscale);
	encoder.set_depth(BitDepth::Eight);

	let mut writer = encoder.write_header().map_err(|err| format!("cannot write header of image: {err}"))?;
	let mut output_data = Vec::with_capacity(blocks.grid_size.element_product() as usize);

	for y in (0..blocks.grid_size.y).rev() {
		let i = (y * blocks.grid_size.x) as usize;
		for &x in &bmap[i..i + blocks.grid_size.x as usize] {
			output_data.push(if x > 0.0 { 0xff } else { 0x00 });
		}
	}

	writer.write_image_data(&output_data).map_err(|err| format!("cannot save image to \"{}\": {err}", output_path.display()))?;
	writer.finish().map_err(|err| format!("cannot flush image data: {err}"))
}

#[cfg(feature = "client")]
fn get_config(path: &Path, level: bool) -> Result<BlockConfig, String> {
	Ok(if level {
		config::load_sync::<LevelConfig>(path)?.blocks
	} else {
		config::load_sync::<MultiplayerConfig>(path)?.blocks
	})
}

#[cfg(not(feature = "client"))]
fn get_config(path: &Path, _level: bool) -> Result<BlockConfig, String> {
	Ok(config::load_sync::<MultiplayerConfig>(path)?.blocks)
}
