using DominionBase.Enums; using DominionBase.Players; using DominionBase.Properties; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; namespace DominionBase.Cards.Menagerie { public class Delay : Event { private readonly Dictionary _SetAsideCards = new Dictionary(); private int _activeIndex = -1; public Delay() : base(Source.Menagerie, 0, Traits.None) { } public override void TearDown(IGame game) { Contract.Requires(game != null, "game cannot be null"); base.TearDown(game); _SetAsideCards.Clear(); foreach (var player in game.Players) { player.TurnStarted -= Player_TurnStarted; player.TurnEnded -= Player_TurnEnded; } } public override void Bought(IPlayer player) { Contract.Requires(player != null, "player cannot be null"); base.Bought(player); if (!player.PlayerMats.ContainsKey(TypeClass.DelaySetAside)) player.PlayerMats[TypeClass.DelaySetAside] = new DelaySetAside(); var setAsideChoice = new Choice(Resource.ChooseCardToSetAside, this, player.Hand[Categories.Action], ChoiceOutcome.Select, player, minimum: 0, maximum: 1); var setAsideResult = player.MakeChoice(setAsideChoice); if (setAsideResult.Cards.Any()) { var card = player.RetrieveCardFrom(DeckLocation.Hand, setAsideResult.Cards[0]); if (!_SetAsideCards.ContainsKey(player)) _SetAsideCards[player] = new CardCollection(); _SetAsideCards[player].Add(card); player.AddCardInto(TypeClass.DelaySetAside, card); player.PlayerMats[TypeClass.DelaySetAside].Refresh(player); player._Game.SendMessage(player, this, "SetAside", card); if (_SetAsideCards[player].Count == 1) player.TurnEnded += Player_TurnEnded; } } private void Player_TurnEnded(object sender, TurnEndedEventArgs e) { e.Player.TurnEnded -= Player_TurnEnded; e.Player.TurnStarted += Player_TurnStarted; } private void Player_TurnStarted(object sender, TurnStartedEventArgs e) { if (!_SetAsideCards.ContainsKey(e.Player)) return; var setAsideCards = _SetAsideCards[e.Player]; for (var i = 0; i < setAsideCards.Count; i++) { var key = $"{Name}_{setAsideCards[i].Name}"; if (!e.HandledBy.Contains(key) && !e.Resolvers.ContainsKey(key)) e.Resolvers[key] = new TurnStartedResolver( e.Player, this, Resource.PlayCard.Replace("{card}", setAsideCards[i].ToString()), (IPlayer player, ref TurnStartedEventArgs eAction) => { _activeIndex = (int)eAction.Resolvers[key].Data; Player_Action(eAction.Player, ref eAction); eAction.HandledBy.Add(key); }, true, i); } } internal void Player_Action(IPlayer player, ref TurnStartedEventArgs e) { if (!_SetAsideCards.ContainsKey(player)) return; var setAsideCards = _SetAsideCards[player]; if (_activeIndex >= 0 && _activeIndex <= setAsideCards.Count) { var setAsideCard = setAsideCards[_activeIndex]; var card = e.Player.RetrieveCardFrom(TypeClass.DelaySetAside, setAsideCard); player._Game.SendMessage(player, this, "Retrieve", setAsideCard); setAsideCards.RemoveAt(_activeIndex); player.Actions++; var previousPlayerMode = player.PutCardIntoPlay(card, Resource.FromCard.Replace("{card}", ToString())); player.PlayCard(card.LogicalCard, previousPlayerMode); e.HandledBy.Add(this); if (!setAsideCards.Any()) e.Player.TurnStarted -= Player_TurnStarted; } } public override void End(IPlayer player, DisplayableCollection collection) { base.End(player, collection); Contract.Requires(collection != null, "collection cannot be null"); // Add back any Delayed cards that are still on this if (_SetAsideCards.ContainsKey(player)) { collection.AddRange(_SetAsideCards[player]); _SetAsideCards[player].Clear(); } } } }