use forge_foundation::ZoneType;
use serde::{Deserialize, Serialize};
use crate::game::GameState;
use crate::parsing::{Params, ParsedParams};
use crate::spellability::SpellAbility;
use super::spell_ability_variables::SpellAbilityVariables;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpellAbilityCondition {
pub variables: SpellAbilityVariables,
}
impl Default for SpellAbilityCondition {
fn default() -> Self {
Self {
variables: SpellAbilityVariables::new(),
}
}
}
impl SpellAbilityCondition {
pub fn new() -> Self {
Self::default()
}
pub fn set_conditions(&mut self, params: &Params) {
self.set_conditions_from(|key| params.get(key));
}
pub fn set_conditions_parsed(&mut self, params: &ParsedParams<'_>) {
self.set_conditions_from(|key| params.get(key));
}
fn set_conditions_from<'a, F>(&mut self, get: F)
where
F: Fn(&str) -> Option<&'a str>,
{
let is_true = |key| get(key).is_some_and(|value| value.eq_ignore_ascii_case("True"));
if let Some(phases_str) = get("ConditionPhases") {
for phase_name in phases_str.split(',') {
if let Some(phase) =
forge_foundation::PhaseType::from_script_name(phase_name.trim())
{
self.variables.add_phase(phase);
}
}
}
if is_true("ConditionPlayerTurn") {
self.variables.set_player_turn(true);
}
if is_true("ConditionOpponentTurn") {
self.variables.set_opponent_turn(true);
}
if is_true("ConditionThreshold") {
self.variables.set_threshold(true);
}
if is_true("ConditionMetalcraft") {
self.variables.set_metalcraft(true);
}
if is_true("ConditionDelirium") {
self.variables.set_delirium(true);
}
if is_true("ConditionHellbent") {
self.variables.set_hellbent(true);
}
if is_true("ConditionRevolt") {
self.variables.set_revolt(true);
}
if is_true("ConditionDesert") {
self.variables.set_desert(true);
}
if is_true("ConditionBlessing") {
self.variables.set_blessing(true);
}
if is_true("ConditionSolved") {
self.variables.set_solved(true);
}
if let Some(present) = get("ConditionPresent") {
self.variables.set_is_present(Some(present.to_string()));
}
if let Some(compare) = get("ConditionCompare") {
self.variables
.set_present_compare(Some(compare.to_string()));
}
if let Some(zone_str) = get("ConditionPresentZone") {
match zone_str.to_lowercase().as_str() {
"battlefield" => self.variables.set_present_zone(ZoneType::Battlefield),
"graveyard" => self.variables.set_present_zone(ZoneType::Graveyard),
"hand" => self.variables.set_present_zone(ZoneType::Hand),
"exile" => self.variables.set_present_zone(ZoneType::Exile),
"library" => self.variables.set_present_zone(ZoneType::Library),
_ => {}
}
}
if let Some(defined) = get("ConditionDefined") {
self.variables
.set_present_defined(Some(defined.to_string()));
}
}
pub fn are_met(&self, game: &GameState, sa: &SpellAbility) -> bool {
let player = sa.activating_player;
let phases = self.variables.phases();
if !phases.is_empty() && !phases.contains(&game.turn.phase) {
return false;
}
let is_players_turn = game.turn.active_player == player;
if self.variables.player_turn() && !is_players_turn {
return false;
}
if self.variables.opponent_turn() && is_players_turn {
return false;
}
if self.variables.hellbent() && !game.player_has_hellbent(player) {
return false;
}
if self.variables.threshold() && !game.player_has_threshold(player) {
return false;
}
if self.variables.metalcraft() && !game.player_has_metalcraft(player) {
return false;
}
if self.variables.delirium() && !game.player_has_delirium(player) {
return false;
}
if self.variables.revolt() && !game.player_has_revolt(player) {
return false;
}
if self.variables.desert() && !game.player_has_desert(player) {
return false;
}
if self.variables.blessing() && !game.player_has_blessing(player) {
return false;
}
if let Some(ref _present_expr) = self.variables.is_present().map(|s| s.to_string()) {
let _zone = self.variables.present_zone();
let _compare = self.variables.present_compare().map(|s| s.to_string());
}
true
}
}