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 an artifact and declaring what it is and what benefits it may provide.
/// See the standard constructor for more detailed information about basic setup.
///
public abstract class Artifact : IArtifact, IComparable, ITableable, IDisposable, IRandomizable, IPoints
{
public virtual event PileChangedEventHandler PileChanged;
public virtual event TokensChangedEventHandler TokensChanged;
internal IGame _Game;
private string _ActionText = string.Empty;
private string _ExtraText = string.Empty;
private readonly Traits _Traits = Traits.Basic;
protected bool AsynchronousChanging { get; private set; }
protected PileChangedEventArgs AsynchronousPileChangedEventArgs { get; private set; }
private int _VictoryPoints;
internal Artifact(Source source, Traits traits, Edition edition = Edition.All)
{
Name = ResourcesHelper.Get($"{source}_{Type.Name}_Name");
Source = source;
if (traits == Traits.None)
_Traits = traits;
else
_Traits |= traits;
Edition = edition;
Text = ResourcesHelper.Get($"{source}_{Type.Name}_Text");
}
internal void Init(IGame game, PlayerCollection players)
{
_Game = game;
}
public static Artifact CreateInstance(Type type)
{
return (Artifact)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.Artifact;
public virtual bool HasCost => false;
public virtual bool HasVPs => VictoryPoints != 0;
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 IDisplayable
public virtual Facing Facing { get; private set; } = Facing.FaceUp;
#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.
}
// 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;
}
}
~Artifact()
{
Dispose(false);
}
#endregion
#region IPoints
public virtual int VictoryPoints
{
get { return _VictoryPoints; }
protected set { _VictoryPoints = value; }
}
public virtual int ComputeVictoryPoints(IPlayer player, IEnumerable collection)
{
return _VictoryPoints;
}
#endregion
#region ITableable Properties
public virtual bool CanUndo => true;
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
#region ITakeable
public virtual bool CanBeMultiples => false;
public virtual void TakenBy(IPlayer player)
{
Contract.Requires(player != null, "player cannot be null");
player._Game.SendMessage(player, this, "Taken");
}
public virtual void ReturnedBy(IPlayer player)
{
Contract.Requires(player != null, "player cannot be null");
player._Game.SendMessage(player, this, "Returned");
}
#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();
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.Invisible;
public virtual Traits Traits => _Traits;
public virtual string SpecialPresetKey => null;
public CardBack CardBack { get; } = CardBack.Standard;
public virtual bool IsStackable => false;
public virtual DisplayableCollection Stack() { return new DisplayableCollection { this }; }
public virtual void Clear() { }
public virtual int GetVictoryPoints(IPlayer player, IEnumerable collection)
{
return 0;
}
public Edition Edition { get; }
public virtual void PerformEndgameCalculations(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(Artifact artifactCard)
{
Contract.Requires(artifactCard != default(Artifact), "artifactCard cannot be null");
if (ReferenceEquals(this, artifactCard))
return 0;
var nc = string.Compare(Name, artifactCard.Name, StringComparison.CurrentCulture);
if (nc == 0)
nc = UniqueId.CompareTo(artifactCard.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 Artifact oArtifact)
return CompareTo(oArtifact);
if (obj is Card || obj is ISupply || obj is Event || obj is Project || obj is Landmark || obj is State || obj is Boon || obj is Hex)
return 1;
if (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;
}
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 xeArtifact = doc.CreateElement("artifact");
return xeArtifact;
}
public static Artifact 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 artifact = CreateInstance(type);
artifact.Load(xnEntity);
return artifact;
}
public void Load(XmlNode xnEntity)
{
if (xnEntity == null)
return;
var artifactType = Type.GetType(xnEntity.Attributes["type"].Value);
var artifact = CreateInstance(artifactType);
//state.LoadInstance(xnEntity);
}
}
}