using System;
using System.Collections;
using System.Collections.Generic;
using Volpe.Cafe;
using Volpe.Cafe.Data;
using Volpe.Cafe.Settings;
namespace Volpe.Cafe.Model
{
    [Serializable]
    public class MarketSimulation
    {
        #region 
        public static void AllocateCosts(Industry data, ModelingSettings settings, Scenario scen, ModelYear year)
        {
            List<Manufacturer> mfrs = data.Manufacturers;
            for (int i = 0, mfrCount = mfrs.Count; i < mfrCount; i++)
            {
                Manufacturer.CModelData mmd = mfrs[i].ModelData;
                List<Vehicle> mfrVehs = mfrs[i].Vehicles;
                int       mfrVehCount = mfrVehs.Count;
                double mfrSales = 0, mfrSalesRevenue = 0, mfrTechCost = 0;
                double mfrFines = mmd.Fines.Total;
                int mfrStrategy = mfrs[i].Description.CostAllocationStrategy;
                for (int j = 0; j < mfrVehCount; j++)
                {
                    Vehicle.CDescription vd = mfrVehs[j].Description;
                    mfrSales        += vd.Sales[year.Index];
                    mfrSalesRevenue += vd.Sales[year.Index] * vd.Msrp[year.Index];
                    mfrTechCost     += vd.Sales[year.Index] * mfrVehs[j].ModelData.TechCost;
                }
                if (mfrStrategy == 3)
                {   
                    for (int j = 0; j < mfrVehCount; j++)
                    {
                        mfrVehs[j].ModelData.RegCost = (mfrTechCost + mfrFines) / mfrSales;
                    }
                } 
                else if (mfrStrategy == 1 || (mfrTechCost == 0 && mfrFines > 0))
                {   
                    double pctIncrease = (mfrTechCost + mfrFines) / mfrSalesRevenue;
                    for (int j = 0; j < mfrVehCount; j++)
                    {
                        mfrVehs[j].ModelData.RegCost = pctIncrease * mfrVehs[j].Description.Msrp[year.Index];
                    }
                } 
                else
                {   
                    for (int j = 0; j < mfrVehCount; j++)
                    {
                        Vehicle.CModelData vmd = mfrVehs[j].ModelData;
                        vmd.RegCost = vmd.TechCost;
                    }
                    if (mfrFines > 0)
                    {
                        double[] vehPseudoFines = new double[mfrVehCount];
                        double   mfrPseudoFines = 0;
                        for (int j = 0; j < mfrVehCount; j++)
                        {
                            vehPseudoFines[j] = GetPseudoFine(mfrs[i], mfrVehs[j], scen, year, settings);
                            mfrPseudoFines   += vehPseudoFines[j];
                        }
                        for (int j = 0; j < mfrVehCount; j++)
                        {
                            double vehSales = mfrVehs[j].Description.Sales[year.Index];
                            if (vehPseudoFines[j] != 0 && vehSales != 0)
                            {
                                mfrVehs[j].ModelData.RegCost += (mfrFines * (vehPseudoFines[j] / mfrPseudoFines)) / vehSales;
                            }
                        }
                    } 
                } 
                mmd.RegCost.Clear();
                for (int j = 0; j < mfrVehCount; j++)
                {
                    Vehicle.CDescription vd = mfrVehs[j].Description;
                    mmd.RegCost[mfrVehs[j].RegClass] += mfrVehs[j].ModelData.RegCost * vd.Sales[year.Index];
                }
            } 
        }
        static double GetPseudoFine(Manufacturer mfr, Vehicle veh, Scenario scen, ModelYear year, ModelingSettings settings)
        {
            double vehSales = veh.Description.Sales[year.Index];
            double vehFE    = Standards.GetAverageFuelEconomy(veh, scen, year, settings, true, true, true);
            double standard = mfr.ModelData.Standard[veh.RegClass];
            return Math.Max(0, scen.ScenInfo[veh.RegClass].FineRate[year.Index] * vehSales * (standard - vehFE));
        }
        #endregion
    }
}

