#region << Using Directives >>
using System;
#endregion
namespace Volpe.Cafe.Generic
{
    [Serializable]
    public class SCValue<T> : ICloneable
    {
        #region 
        public SCValue()
        {
            this.Items = new T[Classes.Length];
        }
        public SCValue(T pc, T lt, T cm)
        {
            this.Items = new T[] { pc, lt, cm };
        }
        #endregion
        #region 
        #region 
        public static bool operator ==(SCValue<T> value1, SCValue<T> value2)
        {
            return Equals(value1, value2);
        }
        public static bool operator !=(SCValue<T> value1, SCValue<T> value2)
        {
            return !Equals(value1, value2);
        }
        #endregion
        #region 
        object ICloneable.Clone()
        {
            return this.Clone();
        }
        public SCValue<T> Clone()
        {
            SCValue<T> value = new SCValue<T>();
            this.CopyTo(value);
            return value;
        }
        protected void CopyTo(SCValue<T> value)
        {
            for (int i = 0; i < this.Items.Length; i++)
            {
                value.Items[i] = this.Items[i];
            }
        }
        #endregion
        #region 
        public override string ToString()
        {
            string s = string.Empty;
            for (int i = 0; i < this.Items.Length; i++)
            {
                if (i > 0) { s += ", "; }
                s += (Names[i] + "=" + this.Items[i].ToString());
            }
            return "{" + s + "}";
        }
        public override int GetHashCode()
        {
            int hash = 0;
            for (int i = 0; i < this.Items.Length; i++)
            {
                hash = hash ^ this.Items[i].GetHashCode();
            }
            return hash;
        }
        public override bool Equals(object obj)
        {
            return (obj is SCValue<T>) ? this.Equals((SCValue<T>)obj) : base.Equals(obj);
        }
        public bool Equals(SCValue<T> value)
        {
            return Equals(this, value);
        }
        public static bool Equals(SCValue<T> value1, SCValue<T> value2)
        {
            if (object.ReferenceEquals(value1, null) && object.ReferenceEquals(value2, null)) { return true; }
            if (object.ReferenceEquals(value1, null) || object.ReferenceEquals(value2, null)) { return false; }
            for (int i = 0; i < value1.Items.Length; i++)
            {
                if (!value1.Items[i].Equals(value2.Items[i])) { return false; }
            }
            return true;
        }
        #endregion
        public void Clear()
        {
            for (int i = 0; i < this.Items.Length; i++)
            {
                this.Items[i] = default(T);
            }
        }
        protected int GetIndex(SafetyClass safetyClass)
        {
            return (int)safetyClass - 1;
        }
        #endregion
        #region 
        public T this[SafetyClass safetyClass]
        {
            get { return this.Items[this.GetIndex(safetyClass)]; }
            set { this.Items[this.GetIndex(safetyClass)] = value; }
        }
        public T[] Items { get; private set; }
        #endregion
        #region 
        public static readonly SafetyClass[] Classes = new SafetyClass[] { SafetyClass.PC,
                                                                           SafetyClass.LT,
                                                                           SafetyClass.CM };
        public static readonly string[] Names = new string[] { "PC",
                                                               "LT",
                                                               "CM" };
        #endregion
    }
}

