using System;
using Volpe.Cafe.EffectsModels;
using Volpe.Cafe.ModelSettings;

namespace Volpe.Cafe.DfsSrModels.Aggregators
{
    [Serializable]
    internal static class ForecastFleetAggregatorUtils
    {
        internal static ForecastFleetData FromHistoricFleetData(HistoricFleetDataItem item, double salesScalar = 1.0d)
        {
            var fleetData = new ForecastFleetData() {
                Sales = item.InitialProduction * salesScalar,
                Share =  1.0d,
                RatedFE = item.OnRoadFE * 1.2, // there is no historic rated-FE info (assume ~20% increase)
                OnRoadFE = item.OnRoadFE,
                FuelShare = item.FuelShare,
                VehiclePower = item.Horsepower,
                CurbWeight = item.CurbWeight,
                RegCost = 0,
                TaxCredit = 0,
                BatteryTaxCredit = 0
            };

            return fleetData;
        }

        internal static void AggregateVehicleData(
            ForecastVehicleData vehData, ForecastFleetData fleetData, Scenario scen, int year, EconomicValues econValues)
        {
            var scenInfo = scen[vehData.RegClass, year];

            var fuelShare   = Effects.GetModifiedVehicleFS(scen, year, vehData.RevisionInfo);
            var fuelEconomy = Effects.CalcRatedVehicleFE(scen, year, vehData.RevisionInfo);

            double vehSales = vehData.Sales;
            FuelValue vehSalesFS = vehSales * fuelShare;
            FuelValue onRoadGap = econValues.Parameters[vehData.VehStyle].OnRoadGap;

            fleetData.Sales += vehSales;
            fleetData.RatedFE += FuelValue.SafeDivide(vehSalesFS, fuelEconomy);
            fleetData.OnRoadFE += FuelValue.SafeDivide(vehSalesFS, fuelEconomy * (FuelValue.One - onRoadGap));
            fleetData.FuelShare += vehSalesFS;
            fleetData.VehiclePower += vehSales * vehData.VehiclePower;
            fleetData.CurbWeight += vehSales * vehData.CurbWeight;
            fleetData.RegCost += vehSales * vehData.RegCost;

            if (scenInfo.ApplyTaxCredits) {
                fleetData.TaxCredit += vehSales * vehData.TaxCredit;
            }
            if (scenInfo.ApplyBatteryTaxCredits) {
                fleetData.BatteryTaxCredit += vehSales * vehData.BatteryTaxCredit;
            }
        }

        internal static void FinalizeFleetData(
            ForecastFleetData carData, ForecastFleetData truckData, ForecastFleetData hdpuvData)
        {
            double totalLdSales = carData.Sales + truckData.Sales;

            FinalizeFleetDataHelper(carData, carData.Sales / totalLdSales);
            FinalizeFleetDataHelper(truckData, truckData.Sales / totalLdSales);
            FinalizeFleetDataHelper(hdpuvData, 1.0d);
        }

        private static void FinalizeFleetDataHelper(ForecastFleetData fleetData, double fleetShare)
        {
            if (fleetData.Sales == 0) {
                return;
            }

            fleetData.Share = fleetShare;
            fleetData.RatedFE = FuelValue.SafeDivide(fleetData.FuelShare, fleetData.RatedFE);
            fleetData.OnRoadFE = FuelValue.SafeDivide(fleetData.FuelShare, fleetData.OnRoadFE);
            fleetData.FuelShare /= fleetData.Sales;
            fleetData.VehiclePower /= fleetData.Sales;
            fleetData.CurbWeight /= fleetData.Sales;
            fleetData.RegCost /= fleetData.Sales;
            fleetData.TaxCredit /= fleetData.Sales;
            fleetData.BatteryTaxCredit /= fleetData.Sales;
        }

    }
}
