#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 CsvAnnualSocietalEffectsReport : CsvReportingBase
    {
        #region 
        static CsvAnnualSocietalEffectsReport()
        {
            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 CsvAnnualSocietalEffectsReport(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.WriteEffectsData(scen, i, ed);
                    }
                }
            }
            ed = compliance.GetEffectsData(scen, year.Year);
            this.WriteEffectsData(scen, year.Year, ed);
            if (year.Year == compliance.MaxYear)
            {   
                for (int i = compliance.MaxYear + 1; i <= compliance.MaxEffectsYear; i++)
                {
                    ed = compliance.GetEffectsData(scen, i);
                    if (ed != null)
                    {
                        this.WriteEffectsData(scen, i, ed);
                    }
                }
            }
        }
        void WriteEffectsData(Scenario scen, int year, EffectsData ed)
        {
            for (int i = 0; i < Interaction.CY; i++)
            {
                int vcCount = 0;
                foreach (VehicleClass vehClass in VehClasses)
                {
                    FuelValue scenVMT = ed.GeneralEffects.VMT.GetValue(vehClass, RegulatoryClass.None);
                    foreach (FuelType fuelType in FuelTypes)
                    {
                        if (scenVMT[fuelType] != 0)
                        {
                            if (vcCount > 1 || vehClass != VehicleClass.All)
                            {
                                this.WriteEffectsData(scen, year, i, vehClass, fuelType, ed);
                            }
                        }
                    }
                    if (scenVMT.Total != 0) { vcCount++; }
                }
            } 
        }
        void WriteEffectsData(Scenario scen, int year, int age, VehicleClass vehClass, FuelType fuelType, EffectsData ed)
        {
            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(ed.GeneralEffects .Fleet               .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.GeneralEffects .VMT                 .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EnergyEffects  .BTU                 .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType) / 1e12);
            this.Write(ed.EnergyEffects  .Gallons             .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EnergyEffects  .NativeUnits         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.SafetyEffects  .Fatalities          .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamCO          .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamVOC         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamNOx         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamSO2         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamPM          .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamCO2         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType) / 1e6);
            this.Write(ed.EmissionEffects.UpstreamCH4         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamN2O         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamAcetaldehyde.GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamAcrolein    .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamBenzene     .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamButadiene   .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamFormaldehyde.GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamDPM10       .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.UpstreamMTBE        .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeCO          .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeVOC         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeNOx         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeSO2         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipePM          .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeCO2         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType) / 1e6);
            this.Write(ed.EmissionEffects.TailpipeCH4         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeN2O         .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeAcetaldehyde.GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeAcrolein    .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeBenzene     .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeButadiene   .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeFormaldehyde.GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeDPM10       .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.TailpipeMTBE        .GetAnnualValue(age, vehClass, RegulatoryClass.None, fuelType));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.CO));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.VOC));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.NOx));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.SO2));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.PM));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.CO2) / 1e6);
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.CH4));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.N2O));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.Acetaldehyde));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.Acrolein));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.Benzene));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.Butadiene));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.Formaldehyde));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.DPM10));
            this.Write(ed.EmissionEffects.GetTotalEmissions(age, vehClass, RegulatoryClass.None, fuelType, Pollutant.MTBE));
            this.NewRow();
        }
        #endregion
        #region 
        public override string ReportName { get { return CsvReportName; } }
        #endregion
        #region 
        public const string CsvReportName = "Annual Societal Effects CSV Report";
        const string Header =
            "Scenario,Scenario Name,Model Year,Age,Calendar Year,Veh-Class,Fuel Type,Fleet,kVMT,Quads,kGallons,kUnits,Fatalities," +
            "CO Upstream (t),VOC Upstream (t),NOx Upstream (t),SO2 Upstream (t),PM Upstream (t),CO2 Upstream (mmt),CH4 Upstream (t),N2O Upstream (t)," +
            "Acetaldehyde Upstream (t),Acrolein Upstream (t),Benzene Upstream (t),Butadiene Upstream (t),Formaldehyde Upstream (t),DPM10 Upstream (t),MTBE Upstream (t)," +
            "CO Tailpipe (t),VOC Tailpipe (t),NOx Tailpipe (t),SO2 Tailpipe (t),PM Tailpipe (t),CO2 Tailpipe (mmt),CH4 Tailpipe (t),N2O Tailpipe (t)," +
            "Acetaldehyde Tailpipe (t),Acrolein Tailpipe (t),Benzene Tailpipe (t),Butadiene Tailpipe (t),Formaldehyde Tailpipe (t),DPM10 Tailpipe (t),MTBE Tailpipe (t)," +
            "CO Total (t),VOC Total (t),NOx Total (t),SO2 Total (t),PM Total (t),CO2 Total (mmt),CH4 Total (t),N2O Total (t)," +
            "Acetaldehyde Total (t),Acrolein Total (t),Benzene Total (t),Butadiene Total (t),Formaldehyde Total (t),DPM10 Total (t),MTBE Total (t)";
        static readonly VehicleClass[] VehClasses;
        static readonly FuelType    [] FuelTypes;
        #endregion
    }
}

