#region << Using Directives >>
using System;
using Volpe.Cafe.Data;
using Volpe.Cafe.Settings;
using Volpe.Cafe.Utils;
using Volpe.Cafe.Model;
using Volpe.Cafe.Generic;
#endregion
namespace Volpe.Cafe.IO.Reporting.CSV
{
    [Serializable]
    public sealed class CsvAnnualSocietalCostsReport : CsvReportingBase
    {
        #region 
        static CsvAnnualSocietalCostsReport()
        {
            int vcCount = VCValue<object>.Classes.Length;
            VehClasses = new VehicleClass[vcCount + 1];
            Array.Copy(VCValue<object>.Classes, VehClasses, vcCount);
            VehClasses[vcCount] = VehicleClass.All;
            int fuelCount = FTValue<object>.Classes.Length;
            FuelTypes = new FuelType[fuelCount + 1];
            Array.Copy(FTValue<object>.Classes, FuelTypes, fuelCount);
            FuelTypes[fuelCount] = FuelType.All;
        }
        public CsvAnnualSocietalCostsReport(string path, bool append) : base(path, append) { }
        #endregion
        #region 
        protected override string GetHeader()
        {
            return Header;
        }
        protected override void ParseData_Internal(Scenario scen, ModelYear year, ICompliance compliance)
        {
            EffectsData ed;
            if (year.Year == compliance.MinYear)
            {   
                for (int i = compliance.MinEffectsYear; i < compliance.MinYear; i++)
                {
                    ed = compliance.GetEffectsData(scen, i);
                    if (ed != null)
                    {
                        this.WriteCostsData(scen, i, ed.UndiscountedCosts);
                        this.WriteCostsData(scen, i, ed.DiscountedCosts);
                    }
                }
            }
            ed = compliance.GetEffectsData(scen, year.Year);
            this.WriteCostsData(scen, year.Year, ed.UndiscountedCosts);
            this.WriteCostsData(scen, year.Year, ed.DiscountedCosts);
            if (year.Year == compliance.MaxYear)
            {   
                for (int i = compliance.MaxYear + 1; i <= compliance.MaxEffectsYear; i++)
                {
                    ed = compliance.GetEffectsData(scen, i);
                    if (ed != null)
                    {
                        this.WriteCostsData(scen, i, ed.UndiscountedCosts);
                        this.WriteCostsData(scen, i, ed.DiscountedCosts);
                    }
                }
            }
        }
        void WriteCostsData(Scenario scen, int year, OwnerAndSocietalCosts osc)
        {
            for (int i = 0; i < Interaction.CY; i++)
            {
                int vcCount = 0;
                foreach (VehicleClass vehClass in VehClasses)
                {
                    FuelValue scenTtl = osc.TotalSocialCosts.GetValue(vehClass, RegulatoryClass.None);
                    foreach (FuelType fuelType in FuelTypes)
                    {
                        if (scenTtl[fuelType] != 0)
                        {
                            if (vcCount > 1 || vehClass != VehicleClass.All)
                            {
                                this.WriteCostsData(scen, year, i, vehClass, fuelType, osc);
                            }
                        }
                    }
                    if (scenTtl.Total != 0) { vcCount++; }
                }
            } 
        }
        void WriteCostsData(Scenario scen, int year, int age, VehicleClass vehClass, FuelType fuelType,
            OwnerAndSocietalCosts osc)
        {
            this.Write(scen.Index);
            this.Write(Interaction.GetTitleCase(scen.Description));
            this.Write(                                         year       .ToString());
            this.Write(                                         age        .ToString());
            this.Write(                                        (year + age).ToString());
            this.Write(vehClass == VehicleClass.All ? "TOTAL" : vehClass   .ToString());
            this.Write(fuelType == FuelType    .All ? "TOTAL" : fuelType   .ToString());
            this.Write(osc.GetDiscountRate(vehClass, RegulatoryClass.None));
            this.Write(osc.PreTaxFuelCosts   .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.FuelTaxCosts      .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.RetailFuelCosts   .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.DriveSurplus      .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.RefuelSurplus     .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.EconomicCosts     .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.CongestionCosts   .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.AccidentCosts     .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.NoiseCosts        .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.FatalityCosts     .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.EmissionsCostsCO  .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.EmissionsCostsVOC .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.EmissionsCostsNOx .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.EmissionsCostsSO2 .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.EmissionsCostsPM  .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.EmissionsCostsCO2 .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.EmissionsCostsCH4 .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.EmissionsCostsN2O .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.TotalConsumerCosts.GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(osc.TotalSocialCosts  .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.NewRow();
        }
        #endregion
        #region 
        public override string ReportName { get { return CsvReportName; } }
        #endregion
        #region 
        public const string CsvReportName = "Annual Societal Costs CSV Report";
        const string Header = "Scenario,Scenario Name,Model Year,Age,Calendar Year,Veh-Class,Fuel Type,Disc-Rate," +
            "Pre-Tax Fuel Cost,Fuel Tax Cost,Retail Fuel Costs,Drive Surplus,Refuel Surplus," +
            "Market Externalities,Congestion Costs,Accident Costs,Noise Costs,Fatality Costs," +
            "CO Damage Costs,VOC Damage Costs,NOx Damage Costs,SO2 Damage Costs,PM Damage Costs,CO2 Damage Costs,CH4 Damage Costs,N2O Damage Costs," +
            "Total Consumer Costs,Total Social Costs";
        static readonly VehicleClass[] VehClasses;
        static readonly FuelType    [] FuelTypes;
        #endregion
    }
}

