// Copyright Marcus Del Favero 2025
// Licensed under the GNU AGPLv3 with an exception, see `README.md` for details
use serde::{Serialize, Deserialize};
use strum_macros::EnumCount;

use crate::utils::max_len::MaxLenArcStr;
use crate::world::colour::Colour;
#[cfg(feature = "client")] use crate::utils::max_len::{MaxLenStr, MaxLenString};

/**
 * A struct for storing all the ways players can present themselves in the game.
 */
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum PlayerStyle {
	Human(HumanStyle),
	Bot(Colour),
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HumanStyle {
	pub name: PlayerName,
	pub colour: Colour,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, EnumCount)]
pub enum PlayerTexture {
	Human,
	Bot,
}

impl PlayerStyle {
	#[cfg(feature = "client")]
	pub fn get_name(&self) -> Option<&PlayerName> {
		match self {
			PlayerStyle::Human(style) => Some(&style.name),
			PlayerStyle::Bot(_) => None,
		}
	}

	pub fn set_name(&mut self, name: PlayerName) {
		match self {
			PlayerStyle::Human(style) => style.name = name,
			PlayerStyle::Bot(_) => (),
		}
	}

	#[cfg(feature = "client")]
	pub fn get_colour(&self) -> Colour {
		match self {
			PlayerStyle::Human(style) => style.colour,
			PlayerStyle::Bot(colour) => *colour,
		}
	}

	pub fn set_colour(&mut self, colour: Colour) {
		match self {
			PlayerStyle::Human(style) => style.colour = colour,
			PlayerStyle::Bot(style_colour) => *style_colour = colour,
		}
	}

	pub(super) fn get_texture(&self) -> PlayerTexture {
		match self {
			PlayerStyle::Human(_) => PlayerTexture::Human,
			PlayerStyle::Bot(_) => PlayerTexture::Bot,
		}
	}
}

impl HumanStyle {
	#[cfg(feature = "client")]
	pub fn override_with(mut self, name: Option<PlayerName>, colour: Option<Colour>) -> HumanStyle {
		if let Some(name) = name { self.name = name; }
		if let Some(colour) = colour { self.colour = colour; }
		self
	}
}

impl PlayerTexture {
	#[cfg(feature = "client")]
	pub fn get_layer(self) -> u32 {
		match self {
			PlayerTexture::Human => 0,
			PlayerTexture::Bot => 1,
		}
	}
}

const MAX_NAME_LEN: usize = 100;

#[cfg(feature = "client")] pub type PlayerNameRef<'a> = MaxLenStr<'a, MAX_NAME_LEN>;
pub type PlayerName = MaxLenArcStr<MAX_NAME_LEN>;
#[cfg(feature = "client")] pub type PlayerNameMut = MaxLenString<MAX_NAME_LEN>;
