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 hex 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 Hex : IHex, 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;
protected bool _AsynchronousChanging { get; private set; }
protected PileChangedEventArgs _AsynchronousPileChangedEventArgs { get; private set; }
private CardBenefit _Benefit;
internal Hex(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 Hex CreateInstance(Type type)
{
return (Hex)Activator.CreateInstance(type);
}
#region ICardBase variables, properties, & methods
public virtual Cost BaseCost { get; } = new Cost();
public Type BaseType => GetType();
public virtual Categories Category { get; } = Categories.Hex;
public virtual bool HasCost => false;
public virtual bool HasVPs => false;
public virtual string SetupText { get; } = string.Empty;
public virtual Source Source { get; } = Source.All;
public string Text
{
get
{
var sb = new StringBuilder();
if (!string.IsNullOrEmpty(_ActionText))
{
if (sb.Length > 0 && !_ActionText.StartsWith("
"))
{
sb.AppendLine();
sb.AppendLine();
}
sb.Append(_ActionText);
}
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);
}
}
}
public virtual List GetSerializingTypes()
{
return new List();
}
#endregion
#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;
}
}
~Hex()
{
Dispose(false);
}
#endregion
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 ITableable Properties
public virtual bool CanUndo => false;
public int Count => 1;
public Orientation Orientation { get; } = Orientation.Landscape;
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 IDisplayable DisplayCard => this;
public virtual Location Location { get; } = Location.Special;
public virtual Traits Traits => _Traits;
public virtual string SpecialPresetKey => null;
public CardBack CardBack { get; } = CardBack.Standard;
public virtual CardBenefit Benefit => _Benefit;
public virtual bool IsStackable => true;
public virtual DisplayableCollection Stack() { return new DisplayableCollection { this }; }
public virtual Facing Facing { get; private set; } = Facing.FaceUp;
public virtual void Clear() { }
public virtual int GetVictoryPoints(IPlayer player, IEnumerable collection)
{
return 0;
}
public Edition Edition { get; }
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(Hex hexCard)
{
Contract.Requires(hexCard != default(Hex), "hexCard cannot be null");
if (ReferenceEquals(this, hexCard))
return 0;
var nc = string.Compare(Name, hexCard.Name, StringComparison.CurrentCulture);
if (nc == 0)
nc = UniqueId.CompareTo(hexCard.UniqueId);
return nc;
}
public int CompareTo(IDisplayable obj)
{
Contract.Requires(obj != default(ITableable), "obj cannot be null");
if (ReferenceEquals(this, obj))
return 0;
if (obj is Hex oHex)
return CompareTo(oHex);
if (obj is Card || obj is ISupply || obj is Event || obj is Project || obj is Landmark || obj is State || obj is Boon)
return 1;
if (obj is Artifact || obj is Way)
return -1;
var nc = string.Compare(Name, obj.Name, StringComparison.CurrentCulture);
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 Hex
///
/// The player receiving the Hex
public virtual void Receive(IPlayer player)
{
Contract.Requires(player != null, "player cannot be null");
player._Game.SendMessage(player, this, "Receive");
}
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)
{
Contract.Requires(doc != null, "doc cannot be null");
var xeHex = doc.CreateElement("hex");
return xeHex;
}
public static Hex Load(IGame game, XmlNode xnEntity)
{
Contract.Requires(xnEntity != null, "xnEntity cannot be null");
var xnType = xnEntity.SelectSingleNode("type");
if (xnType == null)
return null;
var type = Type.GetType(xnType.InnerText);
var hex = CreateInstance(type);
hex.Load(xnEntity);
return hex;
}
public void Load(XmlNode xnEntity)
{
if (xnEntity == null)
return;
var hexType = Type.GetType(xnEntity.Attributes["type"].Value);
var hex = CreateInstance(hexType);
//hex.LoadInstance(xnEntity);
}
}
}