use forge_foundation::ZoneType;
use super::{
emit_zone_trigger, matches_change_type, resolve_defined_player, resolve_numeric_svar,
EffectContext,
};
use crate::card::valid_filter;
use crate::parsing::keys;
#[manabrew_engine_macros::spell_effect(DigUntilEffect)]
fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
let amount = resolve_numeric_svar(ctx.game, sa, keys::AMOUNT, 1).max(0) as usize;
let valid_selector = sa.ir.valid_filter_selector.as_ref();
let valid_filter = sa.ir.valid_filter_text.as_deref().unwrap_or("Card");
let found_dest = sa.ir.found_destination_zone.unwrap_or(ZoneType::Hand);
let revealed_dest = sa.ir.revealed_destination_zone.unwrap_or(ZoneType::Library);
let target_player = sa
.target_chosen
.target_player
.or_else(|| {
sa.defined()
.and_then(|d| resolve_defined_player(d, sa.activating_player, ctx.game))
})
.unwrap_or(sa.activating_player);
let lib_len = ctx
.game
.cards_in_zone(ZoneType::Library, target_player)
.len();
if lib_len == 0 {
return;
}
let mut found = Vec::new();
let mut revealed = Vec::new();
let lib_cards: Vec<_> = ctx
.game
.cards_in_zone(ZoneType::Library, target_player)
.to_vec();
for &cid in lib_cards.iter().rev() {
if found.len() >= amount {
break;
}
revealed.push(cid);
let card = ctx.game.card(cid);
let matches = match (valid_selector, sa.source) {
(Some(selector), Some(source_id)) => valid_filter::matches_valid_card_selector_in_game(
selector,
card,
ctx.game.card(source_id),
ctx.game,
),
_ => matches_change_type(card, valid_filter, &[]),
};
if matches {
found.push(cid);
if let Some(source_id) = sa.source {
if crate::parsing::raw_has_key(&sa.ability_text, keys::FORGET_OTHER_REMEMBERED) {
ctx.game.card_mut(source_id).clear_remembered();
}
if sa.ir.remember_found {
ctx.game.card_mut(source_id).add_remembered_card(cid);
}
if sa.ir.imprint_found {
ctx.game.card_mut(source_id).add_imprinted_card(cid);
}
}
}
}
let rest: Vec<_> = revealed
.iter()
.copied()
.filter(|cid| !found.contains(cid))
.collect();
if let Some(source_id) = sa.source {
if sa.ir.imprint_revealed {
ctx.game
.card_mut(source_id)
.add_imprinted_cards(rest.iter().copied());
}
if sa.ir.remember_revealed {
ctx.game
.card_mut(source_id)
.add_remembered_cards(rest.iter().copied());
}
}
let removed: Vec<_> = revealed.to_vec();
for card_id in removed {
ctx.game
.remove_card_from_zone(ZoneType::Library, target_player, card_id);
}
for &id in &found {
let owner = ctx.game.card(id).owner;
let dest_owner = if found_dest == ZoneType::Battlefield {
sa.activating_player
} else {
owner
};
ctx.move_card(id, found_dest, dest_owner);
if found_dest == ZoneType::Battlefield {
let _ = super::add_to_combat(ctx, sa, id, keys::ATTACKING);
}
emit_zone_trigger(ctx.trigger_handler, id, ZoneType::Library, found_dest);
}
for &id in &rest {
let owner = ctx.game.card(id).owner;
if revealed_dest == ZoneType::Library {
ctx.game
.add_card_to_zone_bottom(ZoneType::Library, owner, id);
ctx.game.card_mut(id).set_zone(ZoneType::Library);
} else {
ctx.move_card(id, revealed_dest, owner);
emit_zone_trigger(ctx.trigger_handler, id, ZoneType::Library, revealed_dest);
}
}
}