using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Xml;
using DominionBase.Enums;
using DominionBase.Piles;
using DominionBase.Players;
namespace DominionBase.Cards
{
///
/// This is the standard abstract class for defining a boon and declaring what it is, what happens when it is taken, and what benefits it may provide.
/// See the standard constructor for more detailed information about basic setup.
///
public abstract class Boon : IBoon, IComparable, IDisposable, IRandomizable, ITableable
{
public virtual event PileChangedEventHandler PileChanged;
public virtual event TokensChangedEventHandler TokensChanged;
internal IGame _Game;
private string _ActionText = "";
private string _ExtraText = string.Empty;
private readonly Traits _Traits = Traits.Basic;
private bool _AsynchronousChanging;
private PileChangedEventArgs _AsynchronousPileChangedEventArgs;
private CardBenefit _Benefit;
internal Boon(Source source, Traits traits, Edition edition = Edition.All)
{
Name = ResourcesHelper.Get($"{source}_{Type.Name}_Name");
Source = source;
_Benefit = new CardBenefit();
if (traits == Traits.None)
_Traits = traits;
else
_Traits |= traits;
Edition = edition;
Text = ResourcesHelper.Get($"{source}_{Type.Name}_Text");
}
public void Init(IGame game, PlayerCollection players)
{
_Game = game;
}
public static Boon CreateInstance(Type type)
{
return (Boon)Activator.CreateInstance(type);
}
#region IDisposable variables, properties, & methods
// Track whether Dispose has been called.
private bool disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if (disposing)
{
// Dispose managed resources.
_Benefit = null;
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.
// Note disposing has been done.
disposed = true;
}
}
~Boon()
{
Dispose(false);
}
#endregion
public virtual List GetSerializingTypes()
{
return new List();
}
public virtual void CheckSetup(Preset preset, ITable table)
{
}
public virtual void CheckSetup(Preset preset, string cardName, IRandomizable card)
{
}
public virtual CardSettingCollection GenerateSettings()
{
return new CardSettingCollection();
}
public virtual void FinalizeSettings(CardSettingCollection settings)
{
}
public Guid UniqueId { get; } = Guid.NewGuid();
#region ICardBase Properties
public virtual Cost BaseCost { get; } = new Cost();
public Type BaseType => GetType();
public virtual Categories Category { get; } = Categories.Boon;
public virtual bool HasCost => false;
public bool HasVPs => false;
public virtual string SetupText => string.Empty;
public virtual Source Source { get; } = Source.All;
public string Text
{
get
{
var sb = new StringBuilder();
var sbBenefitText = new StringBuilder();
if (_Benefit.Any)
sbBenefitText.Append(_Benefit.Text);
if (!string.IsNullOrEmpty(_ActionText))
{
if (sb.Length > 0 && !_ActionText.StartsWith("
", StringComparison.CurrentCulture))
{
sb.AppendLine();
sb.AppendLine();
}
sb.Append(_ActionText.Replace("", sbBenefitText.ToString()));
}
if (!string.IsNullOrEmpty(_ExtraText))
{
sb.Append("
");
sb.AppendLine();
sb.Append(_ExtraText);
}
return sb.ToString();
}
protected set
{
if (value == null)
value = string.Empty;
var strings = value?.Split(new[] { "
" }, StringSplitOptions.None);
if (strings.Length > 0)
{
_ActionText = strings[0].Replace("", Environment.NewLine);
if (strings.Length > 1)
_ExtraText = strings[1].Replace("", Environment.NewLine);
}
if (!_ActionText.Contains(""))
_ActionText = $"{(string.IsNullOrEmpty(_ActionText) ? "" : Environment.NewLine)}{_ActionText}";
}
}
#endregion
#region IDisplayable Properties
public CardBack CardBack { get; } = CardBack.Standard;
public IDisplayable DisplayCard => this;
public Edition Edition { get; }
public virtual Facing Facing { get; private set; } = Facing.FaceUp;
public virtual bool IsStackable => true;
public virtual Location Location { get; } = Location.Special;
public Orientation Orientation { get; } = Orientation.Landscape;
public virtual Traits Traits => _Traits;
#endregion
#region ITableable Properties
public virtual bool CanUndo => false;
public int Count => 1;
public IDisplayable Randomizer => this;
public Type TableableType => Type;
public IEnumerable Types => new List { Type };
#endregion
public Type Type => GetType();
public string Name { get; protected set; }
public string ImageName => Type.Name;
public IDisplayable RootCard => this;
public virtual string SpecialPresetKey => null;
public virtual CardBenefit Benefit => _Benefit;
public virtual DisplayableCollection Stack() { return new DisplayableCollection { this }; }
public virtual void Clear() { }
public virtual int GetVictoryPoints(IPlayer player, IEnumerable collection)
{
return 0;
}
public virtual void End(IPlayer player, PointsCollection collection)
{
}
public void AddPlayer(IPlayer player)
{
Contract.Requires(player != null, "player cannot be null");
player.PhaseChanged += Player_PhaseChangedEvent;
player.PlayerModeChanged += Player_PlayerModeChangedEvent;
}
public void RemovePlayer(IPlayer player)
{
Contract.Requires(player != null, "player cannot be null");
player.PhaseChanged -= Player_PhaseChangedEvent;
player.PlayerModeChanged -= Player_PlayerModeChangedEvent;
}
void Player_PhaseChangedEvent(object sender, PhaseChangedEventArgs e)
{
PhaseChanged(sender, e);
}
void Player_PlayerModeChangedEvent(object sender, PlayerModeChangedEventArgs e)
{
PlayerModeChanged(sender, e);
}
internal virtual void PhaseChanged(object sender, PhaseChangedEventArgs e)
{
}
internal virtual void PlayerModeChanged(object sender, PlayerModeChangedEventArgs e)
{
}
public TokenCollection Tokens { get; } = new TokenCollection();
public void AddToken(Token token)
{
Tokens.Add(token);
if (TokensChanged != null)
{
var etcea = new TokensChangedEventArgs(token);
TokensChanged(this, etcea);
}
var pcea = new PileChangedEventArgs(Operation.Refresh);
if (_AsynchronousChanging)
_AsynchronousPileChangedEventArgs = pcea;
else
PileChanged?.Invoke(this, pcea);
}
public Token RemoveToken(Type tokenType)
{
var foundToken = Tokens.FirstOrDefault(t => t.GetType() == tokenType);
return foundToken != null ? RemoveToken(foundToken) : null;
}
public Token RemoveToken(Token token)
{
Tokens.Remove(token);
if (TokensChanged != null)
{
var etcea = new TokensChangedEventArgs(token);
TokensChanged(this, etcea);
}
var pcea = new PileChangedEventArgs(Operation.Refresh);
if (_AsynchronousChanging)
_AsynchronousPileChangedEventArgs = pcea;
else
PileChanged?.Invoke(this, pcea);
return token;
}
public int CompareTo(Boon boonCard)
{
if (ReferenceEquals(this, boonCard))
return 0;
if (boonCard is null)
return -1;
var nc = string.Compare(Name, boonCard.Name, StringComparison.InvariantCulture);
if (nc == 0)
nc = UniqueId.CompareTo(boonCard.UniqueId);
return nc;
}
public int CompareTo(IDisplayable obj)
{
if (ReferenceEquals(this, obj))
return 0;
if (obj is null)
return -1;
if (obj is Boon oBoon)
return CompareTo(oBoon);
if (obj is Card || obj is ISupply || obj is Event || obj is Project || obj is Landmark || obj is State)
return 1;
if (obj is Hex || obj is Artifact || obj is Way)
return -1;
var nc = string.Compare(Name, obj.Name, StringComparison.InvariantCulture);
if (nc == 0)
nc = UniqueId.CompareTo(obj.UniqueId);
return nc;
}
public int CompareTo(ITableable obj)
{
Contract.Requires(obj != default(ITableable), "obj cannot be null");
if (obj is IDisplayable oDisp)
return CompareTo(oDisp);
return string.Compare(Name, obj.Name, StringComparison.CurrentCulture);
}
public override string ToString()
{
return Name;
}
///
/// The specified player receives the Boon
///
/// The player receiving the Boon
public virtual bool Receive(IPlayer player)
{
Contract.Requires(player != null, "player cannot be null");
player._Game.SendMessage(player, this, "Receive");
player.ReceiveBenefit(this, Benefit);
return true;
}
public virtual void TearDown(IGame game)
{
}
public virtual void BeginChanges()
{
_AsynchronousChanging = true;
_AsynchronousPileChangedEventArgs = null;
}
public virtual void EndChanges()
{
_AsynchronousChanging = false;
if (_AsynchronousPileChangedEventArgs != null)
{
PileChanged?.Invoke(this, _AsynchronousPileChangedEventArgs);
}
_AsynchronousPileChangedEventArgs = null;
}
public virtual void Reset()
{
}
public void FullSetup()
{
Setup();
SnapshotSetup();
FinalizeSetup();
}
public virtual void Setup()
{
}
public virtual void SnapshotSetup()
{
}
public virtual void FinalizeSetup()
{
Finalize(_Game);
}
public virtual void Finalize(IGame game)
{
}
public XmlNode GenerateXml(XmlDocument doc)
{
if (doc == null) throw new ArgumentNullException(nameof(doc));
var xeBoon = doc.CreateElement("boon");
return xeBoon;
}
public static Boon Load(IGame game, XmlNode xnEntity)
{
if (xnEntity == null) throw new ArgumentNullException(nameof(xnEntity));
var xnType = xnEntity.SelectSingleNode("type");
if (xnType == null)
return null;
var type = Type.GetType(xnType.InnerText);
var boon = CreateInstance(type);
boon.Load(xnEntity);
return boon;
}
public void Load(XmlNode xnEntity)
{
if (xnEntity == null)
return;
var boonType = Type.GetType(xnEntity.Attributes["type"].Value);
var boon = CreateInstance(boonType);
//boon.LoadInstance(xnEntity);
}
}
}