using System;
using System.Collections.Generic;
using System.Linq;

namespace Volpe.Cafe.Reporting.ModelingReports
{
    [Serializable]
    internal static class ReportUtils
    {
        private static readonly string[] CriteriaPollutantNames = Pollutants.MonetizedNames.Take(5).ToArray();
        private static readonly string[] GhgPollutantNames = Pollutants.MonetizedNames.Skip(5).ToArray();

        // note: GhgEstimatesNames will need to be refactored as GhgEstimates.Names later on
        private static readonly string[] GhgEstimatesNames = { "Low", "Average", "High", "Very High" };


        public static ReportDataGenerator AsIncremental(this ReportDataGenerator dataGenerator)
        {
            dataGenerator.Flags |= DataGeneratorFlags.Incremental;
            return dataGenerator;
        }

        public static string[] GetComponentReportHeaders(string partialHeader)
        {
            string header =                 
                //----- header columns -----
                $"Scenario,Scenario Name,Model Year,Manufacturer,{partialHeader}," +

                //----- planning info -----
                "Redesign/Refresh," +

                //----- leader info -----
                "Candidate Leader,Candidate Sales,Candidate MSRP," +

                //----- sales & msrp -----
                "Sales Initial,Sales," +
                "Avg MSRP Initial,Avg MSRP," +

                //----- vehicle attributes -----
                "Avg CW Initial,Avg CW," +
                "Avg TW Initial,Avg TW," +
                "Avg GVWR Initial,Avg GVWR," +
                "Avg GCWR Initial,Avg GCWR," +
                "Avg Footprint Initial,Avg Footprint," +

                //----- fuel economy -----
                "Avg Rated FE Initial,Avg Rated FE," +
                "Avg Compliance FE Initial,Avg Compliance FE," +

                //----- tech utilization -----
                "TechKey Initial,TechKey";

            return header.Split(',');
        }

        public static string[] GetSocietalEffectsReportHeaders(string[] headersPrefix)
        {
            List<string> headersSuffix = new List<string> {
                //----- usage and energy effects -----
                "kVMT", "kVMT No Rebound", "Quads", "kGallons", "kUnits",

                //----- safety effects -----
                "Fatalities", "Fatalities From Rebound", "Fatalities From Delta CW",
                "Non-Fatal Injuries", "Non-Fatal Injuries Rebound", "Non-Fatal Injuries Delta CW",
                "Property Damage Crashes", "Property Damage Crashes Rebound", "Property Damage Crashes Delta CW"
            };

            //----- emission health impacts -----
            Array.ForEach(HealthImpacts.Names, item => headersSuffix.Add($"{item} - Upstream"));
            Array.ForEach(HealthImpacts.Names, item => headersSuffix.Add($"{item} - Tailpipe"));
            Array.ForEach(HealthImpacts.Names, item => headersSuffix.Add($"{item} - Total"));

            //----- emission effects -----
            string PollutantUnits(string pollutant)
            {
                return (pollutant == "CO2") ? "(mmt)" : "(t)";
            }

            Array.ForEach(Pollutants.Names, item => headersSuffix.Add($"{item} Upstream {PollutantUnits(item)}"));
            Array.ForEach(Pollutants.Names, item => headersSuffix.Add($"{item} Tailpipe {PollutantUnits(item)}"));
            headersSuffix.Add("PM BTW (t)"); // brake & tire wear is currently only for PM2.5
            Array.ForEach(Pollutants.Names, item => headersSuffix.Add($"{item} Total {PollutantUnits(item)}"));

            string[] headers = new string[headersPrefix.Length + headersSuffix.Count];
            headersPrefix.CopyTo(headers, 0);
            headersSuffix.CopyTo(headers, headersPrefix.Length);

            return headers;
        }

        public static string[] GetSocietalCostsReportHeaders(string[] headersPrefix)
        {
            List<string> headersSuffix = new List<string>() {
                //----- header columns (partial) -----
                "Reg-Class", "Disc-Rate",

                //----- tech, usage, and energy costs -----
                "Foregone Consumer Sales Surplus", "Tech Cost", "Maint/Repair Cost",
                "Implicit Opportunity Cost", "Commercial Operator Implicit Opportunity Cost",
                "Fuel Tax Revenue", "Retail Fuel Outlay", "Drive Value", "Refueling Time Cost",
                "Fatality Risk Value", "Non-Fatal Risk Value",
                "Petroleum Market Externalities", "Congestion Costs", "Noise Costs",

                //----- safety costs -----
                "Fatality Costs", "Fatality Costs Rebound", "Fatality Costs Delta CW",
                "Non-Fatal Injury Costs", "Non-Fatal Injury Costs Rebound", "Non-Fatal Injury Costs Delta CW",
                "Property Damage Crash Costs", "Property Damage Crash Costs Rebound",
                "Property Damage Crash Costs Delta CW"
            };

            //----- emission damage costs -----
            Array.ForEach(CriteriaPollutantNames, item => headersSuffix.Add($"{item} Damage Costs"));

            //----- GHG emission damage costs (at various estimates) -----
            Array.ForEach(GhgPollutantNames, item => AppendEstimates($"{item} Damage Costs"));

            //----- costs and benefits subtotals (at various estimates) -----
            headersSuffix.Add("Total Social Costs");
            AppendEstimates("Total Social Benefits", "SCC ");
            AppendEstimates("Net Social Benefits", "SCC ");

            string[] headers = new string[headersPrefix.Length + headersSuffix.Count];
            headersPrefix.CopyTo(headers, 0);
            headersSuffix.CopyTo(headers, headersPrefix.Length);

            return headers;

            void AppendEstimates(string item, string prefix = "")
            {
                Array.ForEach(GhgEstimatesNames, estimate => headersSuffix.Add($"{item} ({prefix}{estimate})"));
            }
        }

    }
}
