using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Serialization.Formatters.Binary; namespace DominionBase.Cards { [Serializable] public abstract class CardSetting { private object _Value; public virtual string Name => string.Empty; public virtual string Text => Name; public virtual string Hint => Name; public virtual Type Type => typeof(object); public virtual int DisplayOrder => -1; public object Value { get { return _Value; } set { Contract.Requires(value != null, "value cannot be null"); if (value.GetType() != Type) throw new ArgumentException($"Type of object is not correct -- expected {Type}"); MethodInfo miCompareTo = null; if (UseLowerBounds) { var success = false; miCompareTo = Type.GetMethod("CompareTo", new Type[] { Type }); if (miCompareTo != null) { var returnObject = miCompareTo.Invoke(value, new object[] { LowerBounds }); if (returnObject is int roInt) success = roInt == 1 || (IsLowerBoundsInclusive && roInt == 0); } if (!success) throw new ArgumentOutOfRangeException("Value is too small for bounds"); } if (UseUpperBounds) { var success = false; if (miCompareTo == null) miCompareTo = Type.GetMethod("CompareTo", new Type[] { Type }); if (miCompareTo != null) { var returnObject = miCompareTo.Invoke(value, new object[] { UpperBounds }); if (returnObject is int roInt) success = roInt == -1 || (IsUpperBoundsInclusive && roInt == 0); } if (!success) throw new ArgumentOutOfRangeException("Value is too large for bounds"); } _Value = value; } } public virtual object LowerBounds => null; public virtual bool UseLowerBounds => false; public virtual bool IsLowerBoundsInclusive => true; public virtual object UpperBounds => null; public virtual bool UseUpperBounds => false; public virtual bool IsUpperBoundsInclusive => true; } [Serializable] public class CardSettingCollection : List { public bool ContainsKey(Type tSetting) { return Exists(cs => cs.GetType() == tSetting); } public CardSetting this[Type tSetting] { get { return Find(cs => cs.GetType() == tSetting); } set { var foundCS = this.FirstOrDefault(cs => cs.GetType() == tSetting); if (foundCS != null) Remove(foundCS); Add(value); } } public bool Remove(Type tSetting) { if (!ContainsKey(tSetting)) return false; Remove(this.First(cs => cs.GetType() == tSetting)); return true; } } [Serializable] public class CardsSettings { public string Name { get; set; } public CardSettingCollection CardSettingCollection { get; } = new CardSettingCollection(); public IOrderedEnumerable CardSettingOrdered { get { return CardSettingCollection.OrderBy(cs => cs.DisplayOrder); } } private CardsSettings() { } public CardsSettings(string cardName) { Name = cardName; } } [Serializable] public class CardsSettingsCollection : List { public bool ContainsKey(string cardName) { return Exists(cs => cs.Name == cardName); } public CardsSettings this[string cardName] { get { return Find(cs => cs.Name == cardName); } set { var foundCS = this.FirstOrDefault(cs => cs.Name == cardName); if (foundCS != null) Remove(foundCS); Add(value); } } public bool Remove(string cardName) { if (!ContainsKey(cardName)) return false; Remove(this.First(cs => cs.Name == cardName)); return true; } public CardsSettingsCollection DeepClone() { using (var ms = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(ms, this); ms.Position = 0; return (CardsSettingsCollection)formatter.Deserialize(ms); } } } }