using System;
using Volpe.Cafe.Generic;

namespace Volpe.Cafe.EffectsData.Collections
{
    /// <summary>
    /// Provides a class to store a collection of modeling effects values that are aggregated by regulatory class and
    /// fuel type.
    /// </summary>
    /// <remarks>
    /// This object supports and operates on all regulatory classes as defined by <see cref="RegClasses.AltList"/> as
    /// well as all fuel types as defined by <see cref="FuelTypes.List"/>.
    /// </remarks>
    /// <typeparam name="T">The type of the elements encapsulated by the modeling effects collection.</typeparam>
    [Serializable]
    public class ModelingEffectsCollection<T> where T : IAppendable, new()
    {
        /// <summary>
        /// Specifies the underlying object of modeling effects values for each regulatory class and fuel type.
        /// </summary>
        protected RCAltValue<FTValue<T>> _values = new RCAltValue<FTValue<T>>(() => new FTValue<T>(() => new T()));

        /// <summary>
        /// Gets a modeling effects value for the specified regulatory class and fuel type.
        /// </summary>
        public virtual T this[RegulatoryClass regClass, FuelType fuelType]
        {
            get {
                switch (regClass) {
                    case RegulatoryClass.All:
                        var all = new T();
                        for (int i = 0; i < this._values.Items.Length; i++) {
                            all.Append(this._values.Items[i].GetValue(fuelType));
                        }
                        return all;

                    case RegulatoryClass.AllLightDuty:
                        var allLd = new T();
                        allLd.Append(this._values.PassengerCar.GetValue(fuelType));
                        allLd.Append(this._values.LightTruck.GetValue(fuelType));
                        return allLd;

                    default:
                        return this._values[regClass].GetValue(fuelType);
                }
            }
        }

        /// <summary>
        /// Gets a modeling effects value for the regulatory class associated with the specified <paramref
        /// name="regClassIndex"/> and the fuel type associated with the specified <paramref name="fuelTypeIndex"/>.
        /// </summary>
        public T this[int regClassIndex, int fuelTypeIndex] => this._values.Items[regClassIndex].Items[fuelTypeIndex];

        /// <summary>
        /// Resets all modeling effects values to zero.
        /// </summary>
        public void Clear()
        {
            this._values.Clear(item => item.Clear(subItem => subItem.Clear()));
        }

        /// <summary>
        /// Appends all modeling effects values from the specified <paramref name="value"/> to this instance.
        /// </summary>
        public void Append(ModelingEffectsCollection<T> value)
        {
            for (int i = 0; i < this._values.Items.Length; i++) {
                this._values.Items[i].Append(value._values.Items[i]);
            }
        }

    }
}
