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 Reap : Event { private readonly Dictionary _SetAsideCards = new Dictionary(); private readonly Dictionary _SetAsideCardsNextTurn = new Dictionary(); private int _activeIndex = -1; public Reap() : base(Source.Menagerie, 7, Traits.Gainer) { } public override void TearDown(IGame game) { Contract.Requires(game != null, "game cannot be null"); base.TearDown(game); _SetAsideCards.Clear(); _SetAsideCardsNextTurn.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.ReapSetAside)) player.PlayerMats[TypeClass.ReapSetAside] = new ReapSetAside(); player.CardGained += Player_CardGained; player.Gain(player._Game.Table.Gold, this); } private void Player_CardGained(object sender, CardGainEventArgs e) { var player = sender as IPlayer; var key = Type.ToString(); // Already been cancelled -- don't need to process this one // If the card has been "lost track of", then we can skip calling it if (e.Cancelled || e.IsLostTrackOf) { player.CardGained -= Player_CardGained; return; } // We've already got a resolver for this in the queue if (e.Resolvers.ContainsKey(key)) return; e.Resolvers[key] = new CardGainResolver(player, this, "SetAside", Resource.SetAside, Player_SetAside, true); } internal void Player_SetAside(IPlayer player, ref CardGainEventArgs e) { var c = player.RetrieveCardFrom(e.Location, e.Card); e.Cancelled = true; e.Location = DeckLocation.PlayerMat; if (!_SetAsideCardsNextTurn.ContainsKey(player)) _SetAsideCardsNextTurn[player] = new CardCollection(); _SetAsideCardsNextTurn[player].Add(c); player.AddCardInto(TypeClass.ReapSetAside, c); player.PlayerMats[TypeClass.ReapSetAside].Refresh(player); player._Game.SendMessage(player, this, "SetAside", c); if (_SetAsideCardsNextTurn[player].Count == 1) player.TurnEnded += Player_TurnEnded; e.HandledBy.Add(this); player.CardGained -= Player_CardGained; } private void Player_TurnEnded(object sender, TurnEndedEventArgs e) { e.Player.TurnEnded -= Player_TurnEnded; foreach (var player in _SetAsideCardsNextTurn.Keys) { if (!_SetAsideCards.ContainsKey(player)) _SetAsideCards[player] = new CardCollection(); _SetAsideCards[player].Clear(); _SetAsideCards[player].AddRange(_SetAsideCardsNextTurn[player]); } _SetAsideCardsNextTurn.Clear(); 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.ReapSetAside, setAsideCard); //player._Game.SendMessage(player, this, "Retrieve", setAsideCard); if (setAsideCard.Category.HasFlag(Categories.Action)) player.Actions++; var previousPlayerMode = player.PutCardIntoPlay(setAsideCard, Resource.FromCard.Replace("{card}", ToString())); player.PlayCard(setAsideCard.LogicalCard, previousPlayerMode); setAsideCards.RemoveAt(_activeIndex); 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(); } } } }