// Copyright Marcus Del Favero 2025
// Licensed under the GNU AGPLv3 with an exception, see `README.md` for details
use strum_macros::EnumIter;

use crate::world::effects::Effect;
use crate::utils::ToStr;

// INVARIANT: 0 <= self.0 <= 1
#[derive(Clone, Copy)]
pub struct Underpower(f32);

impl Underpower {
	pub fn get(self) -> f32 { self.0 }
}

impl TryFrom<f32> for Underpower {
	type Error = ();

	fn try_from(power: f32) -> Result<Underpower, ()> {
		(0.0..=1.0).contains(&power).then_some(Underpower(power)).ok_or(())
	}
}

#[derive(Clone, Copy, EnumIter)]
pub enum UnderpowerEffect {
	Speed,
	Reload,
	Regeneration,
	Damage,
}

impl ToStr for UnderpowerEffect {
	fn to_str(self) -> &'static str {
		match self {
			UnderpowerEffect::Speed => "speed",
			UnderpowerEffect::Reload => "reload",
			UnderpowerEffect::Regeneration => "regen",
			UnderpowerEffect::Damage => "damage",
		}
	}
}

impl UnderpowerEffect {
	pub fn try_from(s: &str) -> Option<UnderpowerEffect> {
		match s {
			"speed" => Some(UnderpowerEffect::Speed),
			"reload" => Some(UnderpowerEffect::Reload),
			"regen" | "regeneration" => Some(UnderpowerEffect::Regeneration),
			"damage" => Some(UnderpowerEffect::Damage),
			_ => None,
		}
	}

	pub fn to_effect(self) -> Effect {
		match self {
			UnderpowerEffect::Speed => Effect::Speed,
			UnderpowerEffect::Reload => Effect::Reload,
			UnderpowerEffect::Regeneration => Effect::Regeneration,
			UnderpowerEffect::Damage => Effect::Damage,
		}
	}
}

pub enum UnderpowerCommand {
	Clear(Option<UnderpowerEffect>),
	Status(Option<UnderpowerEffect>),
	Change(UnderpowerEffect, Underpower),
}
