#region << Using Directives >>
using System;
#endregion
namespace Volpe.Cafe.Generic
{
    [Serializable]
    public class FTValue<T> : ICloneable
    {
        #region 
        public FTValue()
        {
            this.Items = new T[Classes.Length];
        }
        public FTValue(T gasoline, T ethanol85, T diesel, T biodiesel20, T electricity, T hydrogen, T cng, T lng, T lpg)
        {
            this.Items = new T[] { gasoline, ethanol85, diesel, biodiesel20, electricity, hydrogen, cng, lng, lpg };
        }
        #endregion
        #region 
        #region 
        public static bool operator ==(FTValue<T> value1, FTValue<T> value2)
        {
            return Equals(value1, value2);
        }
        public static bool operator !=(FTValue<T> value1, FTValue<T> value2)
        {
            return !Equals(value1, value2);
        }
        #endregion
        #region 
        object ICloneable.Clone()
        {
            return this.Clone();
        }
        public FTValue<T> Clone()
        {
            FTValue<T> value = new FTValue<T>();
            this.CopyTo(value);
            return value;
        }
        protected void CopyTo(FTValue<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 FTValue<T>) ? this.Equals((FTValue<T>)obj) : base.Equals(obj);
        }
        public bool Equals(FTValue<T> value)
        {
            return Equals(this, value);
        }
        public static bool Equals(FTValue<T> value1, FTValue<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(FuelType fuelType)
        {
            if      (fuelType == FuelType.Gasoline   ) { return  0; }
            else if (fuelType == FuelType.Ethanol85  ) { return  1; }
            else if (fuelType == FuelType.Diesel     ) { return  2; }
            else if (fuelType == FuelType.Biodiesel20) { return  3; }
            else if (fuelType == FuelType.Electricity) { return  4; }
            else if (fuelType == FuelType.Hydrogen   ) { return  5; }
            else if (fuelType == FuelType.CNG        ) { return  6; }
            else if (fuelType == FuelType.LNG        ) { return  7; }
            else if (fuelType == FuelType.LPG        ) { return  8; }
            else                                       { return -1; }
        }
        #endregion
        #region 
        public T this[FuelType fuelType]
        {
            get { return this.Items[this.GetIndex(fuelType)]; }
            set { this.Items[this.GetIndex(fuelType)] = value; }
        }
        public T[] Items { get; private set; }
        public bool IsMultiFuel
        {
            get
            {
                int f = (int)this.FuelType;
                return ((f & (f - 1)) != 0);
            }
        }
        public FuelType FuelType
        {
            get
            {
                FuelType fuelType = FuelType.None;
                for (int i = 0; i < this.Items.Length; i++)
                {
                    if (this.Items[i] != null && !this.Items[i].Equals(default(T))) { fuelType |= Classes[i]; }
                }
                return fuelType;
            }
        }
        #endregion
        #region 
        public static readonly FuelType[] Classes  = new FuelType[] { FuelType.Gasoline,
                                                                      FuelType.Ethanol85,
                                                                      FuelType.Diesel,
                                                                      FuelType.Biodiesel20,
                                                                      FuelType.Electricity,
                                                                      FuelType.Hydrogen,
                                                                      FuelType.CNG,
                                                                      FuelType.LNG,
                                                                      FuelType.LPG };
        public static readonly string  [] Names    = new string  [] { "Gasoline",
                                                                      "Ethanol-85%",
                                                                      "Diesel",
                                                                      "Biodiesel-20%",
                                                                      "Electricity",
                                                                      "Hydrogen",
                                                                      "Compressed Natural Gas",
                                                                      "Liquefied Natural Gas",
                                                                      "Liquefied Petroleum Gas" };
        public static readonly string  [] Acronyms = new string  [] { "G",
                                                                      "E85",
                                                                      "D",
                                                                      "B20",
                                                                      "E",
                                                                      "H",
                                                                      "CNG",
                                                                      "LNG",
                                                                      "LPG" };
        #endregion
    }
}

