using System;
using Volpe.Cafe.Generic;

namespace Volpe.Cafe.EffectsData.Collections
{
    /// <summary>
    /// Provides a collection of modeling effects related to various general vehicle attributes, separated by
    /// regulatory class and fuel type.
    /// </summary>
    /// <inheritdoc cref="ModelingEffectsCollection{T}" path="/remarks"/>
    [Serializable]
    public sealed class GeneralEffectsCollection : ModelingEffectsCollection<GeneralEffects>
    {
        /// <summary>
        /// Gets a modeling effects value for the specified regulatory class and fuel type.
        /// </summary>
        public override GeneralEffects this[RegulatoryClass regClass, FuelType fuelType]
        {
            get {
                int rcIndex = regClass.GetAltListIndex();
                int ftIndex = fuelType.GetListIndex();

                return (rcIndex == -1 || ftIndex == -1)
                    ? this.GetValueAggregateClasses(regClass, fuelType)
                    : this[rcIndex, ftIndex]; // individual classes and fuels
            }
        }

        private GeneralEffects GetValueAggregateClasses(RegulatoryClass regClass, FuelType fuelType)
        {
            double salesSum = 0;
            double cwSum = 0;
            double fpSum = 0;
            double wfSum = 0;

            switch (regClass) {
                case RegulatoryClass.All:
                    foreach (var item in this._values.Items) {
                        AggregateValues(item);
                    }
                    break;

                case RegulatoryClass.AllLightDuty:
                    AggregateValues(this._values.PassengerCar);
                    AggregateValues(this._values.LightTruck);
                    break;

                default:
                    AggregateValues(this._values[regClass]);
                    break;
            }

            var value = new GeneralEffects();
            if (salesSum != 0) {
                value.Sales = salesSum;
                value.CurbWeight = cwSum / salesSum;
                value.Footprint = fpSum / salesSum;
                value.WorkFactor = wfSum / salesSum;
            }
            return value;

            // local helper function
            void AggregateValues(FTValue<GeneralEffects> item)
            {
                foreach (var ft in FuelTypes.List) {
                    if (!fuelType.Contains(ft)) {
                        continue;
                    }

                    GeneralEffects subItem = item[ft];
                    salesSum += subItem.Sales;
                    cwSum += subItem.Sales * subItem.CurbWeight;
                    fpSum += subItem.Sales * subItem.Footprint;
                    wfSum += subItem.Sales * subItem.WorkFactor;
                }
            }
        }

    }
}
