#region << Using Directives >>
using System;
using Volpe.Cafe.IO.Reporting.CSV;
using Volpe.Cafe.Settings;
using Volpe.Cafe.Model;
using Volpe.Cafe.MonteCarlo.Model;
using Volpe.Cafe.MonteCarlo.Data;
using Volpe.Cafe.Generic;
using Volpe.Cafe.Data;
#endregion
namespace Volpe.Cafe.MonteCarlo.IO.Reporting
{
    [Serializable]
    public class CsvMonteCarloReport : CsvReportingBase
    {
        #region 
        public CsvMonteCarloReport(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)
        {
            MonteCarloModel mcModel = (MonteCarloModel)compliance;
            this._minYear = mcModel.MinYear;
            this._maxYear = mcModel.MaxYear;
            if (year.Year < this._maxYear) { return; }
            TrialData[] data = mcModel.GetTrialData(scen);
            for (int i = 0; i < data.Length; i++)
            {
                for (int j = this._minYear; j <= this._maxYear; j++)
                {
                    this.WriteMonteCarloData(scen, j, data[i]);
                }
                this.WriteMonteCarloData(scen, -1, data[i]);
            }
        }
        void WriteMonteCarloData(Scenario scen, int year, TrialData data)
        {
            if (!data.HasData) { return; }
            int yr = (year == -1) ? 0 : year - this._minYear;
            int rcCount = 0;
            foreach (RegulatoryClass regClass in RCValue<object>.Classes)
            {
                if (data.Sales[yr][regClass] != 0)
                {
                    this.WriteMonteCarloData(scen, year, regClass, data);
                    rcCount++;
                }
            }
            if (rcCount > 1)
            {   
                this.WriteMonteCarloData(scen, year, RegulatoryClass.All, data);
            }
        }
        void WriteMonteCarloData(Scenario scen, int year, RegulatoryClass regClass, TrialData data)
        {
            int yr = year - this._minYear;
            this.Write(data.TrialInfo.Index);
            this.Write(year     == -1                  ? "TOTAL" : year    .ToString());
            this.Write(regClass == RegulatoryClass.All ? "TOTAL" : regClass.ToString());
            if (year == -1)
            {
                this.WriteEmpty(7);
                this.WriteArraySum(data.TechCosts      , regClass);
                this.WriteArraySum(data.DiscCosts      , regClass);
                this.WriteArraySum(data.Fines          , regClass);
                this.WriteArraySum(data.TotalTechCosts , regClass);
                this.WriteArraySum(data.VMT            , regClass);
                this.WriteArraySum(data.FuelConsumption, regClass);
                this.WriteArraySum(data.CO2Emissions   , regClass);
                this.WriteArraySum(data.Fatalities     , regClass);
                this.WriteArraySum(data.PreTaxFuelCosts, regClass);
                this.WriteArraySum(data.SocialCosts    , regClass);
                this.WriteArraySum(data.NetBenefits    , regClass);
                this.WriteEmpty(5);
            }
            else
            {
                if (regClass == RegulatoryClass.All)
                {
                    this.Write(data.Standard    [yr].HarmonicMean  (data.Sales[yr]));
                    this.Write(data.CAFE        [yr].HarmonicMean  (data.Sales[yr]));
                    this.Write(data.CurbWeight  [yr].ArithmeticMean(data.Sales[yr]));
                    this.Write(data.WorkFactor  [yr].ArithmeticMean(data.Sales[yr]));
                    this.Write(data.AvgTechCosts[yr].ArithmeticMean(data.Sales[yr]));
                    this.Write(data.AvgIncrCosts[yr].ArithmeticMean(data.Sales[yr]));
                    this.WriteEmpty(1); 
                }
                else
                {
                    this.Write(data.Standard    [yr][regClass]);
                    this.Write(data.CAFE        [yr][regClass]);
                    this.Write(data.CurbWeight  [yr][regClass]);
                    this.Write(data.WorkFactor  [yr][regClass]);
                    this.Write(data.AvgTechCosts[yr][regClass]);
                    this.Write(data.AvgIncrCosts[yr][regClass]);
                    this.Write(data.AvgPayback  [yr][regClass]);
                }
                this.Write(data.TechCosts       [yr].GetValue(regClass));
                this.Write(data.DiscCosts       [yr].GetValue(regClass));
                this.Write(data.Fines           [yr].GetValue(regClass));
                this.Write(data.TotalTechCosts  [yr].GetValue(regClass));
                this.Write(data.VMT             [yr].GetValue(regClass));
                this.Write(data.FuelConsumption [yr].GetValue(regClass));
                this.Write(data.CO2Emissions    [yr].GetValue(regClass));
                this.Write(data.Fatalities      [yr].GetValue(regClass));
                this.Write(data.PreTaxFuelCosts [yr].GetValue(regClass));
                this.Write(data.SocialCosts     [yr].GetValue(regClass));
                this.Write(data.NetBenefits     [yr].GetValue(regClass));
                if (regClass == RegulatoryClass.All)
                {
                    this.Write(data.TechUseLGDI [yr].ArithmeticMean(data.Sales[yr]));
                    this.Write(data.TechUseISG  [yr].ArithmeticMean(data.Sales[yr]));
                    this.Write(data.TechUseSHEV [yr].ArithmeticMean(data.Sales[yr]));
                    this.Write(data.TechUseROLL1[yr].ArithmeticMean(data.Sales[yr]));
                    this.Write(data.TechUseMR2  [yr].ArithmeticMean(data.Sales[yr]));
                }
                else
                {
                    this.Write(data.TechUseLGDI [yr][regClass]);
                    this.Write(data.TechUseISG  [yr][regClass]);
                    this.Write(data.TechUseSHEV [yr][regClass]);
                    this.Write(data.TechUseROLL1[yr][regClass]);
                    this.Write(data.TechUseMR2  [yr][regClass]);
                }
            }
            this.NewRow();
        }
        void WriteArraySum(RCDouble[] value, RegulatoryClass regClass)
        {
            double sum = 0;
            for (int i = 0; i < value.Length; i++)
            {
                sum += value[i].GetValue(regClass);
            }
            this.Write(sum);
        }
        #endregion
        #region 
        public override string ReportName { get { return CsvReportName; } }
        #endregion
        #region 
        public const string CsvReportName = "Monte-Carlo CSV Report";
        const string Header =
            "Trial,Model Year,Reg-Class,Standard,CAFE,Average CW,Average WF," +
            "Avg.Tech Costs,Avg.Incr Costs,Avg.Payback,Tech Costs,Disc Tech Costs,Fines,Total Tech Costs," +
            "VMT,Fuel Consumption,CO2 Emissions,Fatalities,Pre-Tax Fuel Costs,Social Costs,Net Benefits," +
            "Tech Use LGDI,Tech Use ISG,Tech Use SHEV,Tech Use ROLL1,Tech Use MR2";
        int _minYear, _maxYear;
        #endregion
    }
}

