#region << Using Directives >>
using System;
#endregion
namespace Volpe.Cafe.Generic
{
    [Serializable]
    public class VCValue<T> : ICloneable
    {
        #region 
        public VCValue()
        {
            this.Items = new T[Classes.Length];
        }
        public VCValue(T ldv, T ldt12a, T ldt2b3, T mdt456)
        {
            this.Items = new T[] { ldv, ldt12a, ldt2b3, mdt456 };
        }
        #endregion
        #region 
        #region 
        public static bool operator ==(VCValue<T> value1, VCValue<T> value2)
        {
            return Equals(value1, value2);
        }
        public static bool operator !=(VCValue<T> value1, VCValue<T> value2)
        {
            return !Equals(value1, value2);
        }
        #endregion
        #region 
        object ICloneable.Clone()
        {
            return this.Clone();
        }
        public VCValue<T> Clone()
        {
            VCValue<T> value = new VCValue<T>();
            this.CopyTo(value);
            return value;
        }
        protected void CopyTo(VCValue<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 VCValue<T>) ? this.Equals((VCValue<T>)obj) : base.Equals(obj);
        }
        public bool Equals(VCValue<T> value)
        {
            return Equals(this, value);
        }
        public static bool Equals(VCValue<T> value1, VCValue<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(VehicleClass vehClass)
        {
            switch (vehClass)
            {
                case VehicleClass.LDV   : return  0;
                case VehicleClass.LDT1  :
                case VehicleClass.LDT2a :
                case VehicleClass.LDT12a: return  1;
                case VehicleClass.LDT2b :
                case VehicleClass.LDT3  :
                case VehicleClass.LDT2b3: return  2;
                case VehicleClass.MDT4  :
                case VehicleClass.MDT5  :
                case VehicleClass.MDT6  :
                case VehicleClass.MDT456: return  3;
                default:                  return -1;
            }
        }
        #endregion
        #region 
        public T this[VehicleClass vehClass]
        {
            get { return this.Items[this.GetIndex(vehClass)]; }
            set { this.Items[this.GetIndex(vehClass)] = value; }
        }
        public T[] Items { get; private set; }
        #endregion
        #region 
        public static readonly VehicleClass[] Classes = new VehicleClass[] { VehicleClass.LDV,
                                                                             VehicleClass.LDT12a,
                                                                             VehicleClass.LDT2b3,
                                                                             VehicleClass.MDT456 };
        public static readonly string[] Names = new string[] { "LDV",
                                                               "LDT12a",
                                                               "LDT2b3",
                                                               "MDT456" };
        #endregion
    }
}

