using System;

namespace BS.Shared.Core
{
	public interface IEnumValue : IComparable
	{
		Enum Enum { get; }
		String DisplayText { get; }
	}

	public class EnumValue<T> : IComparable<EnumValue<T>>, IEnumValue
		where T : struct, IComparable, IFormattable, IConvertible // where T : Enum is not possible
	{
		public T Enum { get; private set; }
		public String DisplayText { get; private set; }

		public EnumValue(T key, String displayText)
		{
			if (displayText == null) throw new ArgumentNullException("displayText");

			Enum = key;
			DisplayText = displayText;
		}

		int IComparable<EnumValue<T>>.CompareTo(EnumValue<T> other)
		{
			var result = String.Compare(DisplayText, other.DisplayText, StringComparison.CurrentCulture);
			if (result == 0)
			{
				var thisInt = Utils.ToInt(Enum);
				var otherInt = Utils.ToInt(other.Enum);
				if (thisInt > otherInt)
				{
					return 1;
				}
				if (thisInt < otherInt)
				{
					return -1;
				}
				return 0;
			}
			return result;
		}

		public override String ToString()
		{
			return DisplayText;
		}

		public override bool Equals(Object obj)
		{
			if (ReferenceEquals(this, obj))
				return true;
			if (!(obj is EnumValue<T>))
				return false;
			var castOther = (EnumValue<T>)obj;
			return Equals(Enum, castOther.Enum);
		}

		public static bool operator ==(EnumValue<T> v1, EnumValue<T> v2)
		{
			return Equals(v1, v2);
		}

		public static bool operator !=(EnumValue<T> v1, EnumValue<T> v2)
		{
			return !(v1 == v2);
		}

		public override int GetHashCode()
		{
			return this.Enum.GetHashCode();
		}

		Enum IEnumValue.Enum
		{
			get { return (Enum)(Object)Enum; }
		}

		int IComparable.CompareTo(Object obj)
		{
			return ((IComparable<EnumValue<T>>)this).CompareTo(obj as EnumValue<T>);
		}
	}
}