using System.Collections.Generic;
using Volpe.Cafe.MarketData.Design;
using Volpe.Cafe.ModelSettings;
using Volpe.Cafe.Utils;
using Volpe.Cafe.VehicleSimulation;

using TI = Volpe.Cafe.TechnologyIndexes;

namespace Volpe.Cafe.Reporting.Generators
{
    /// <summary>
    /// Defines an enumerable object used for generating rows of data for a vehicles battery and motor report.
    /// </summary>
    class VehiclesBatteryMotorReportDataGenerator : ReportDataGenerator
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="VehiclesBatteryMotorReportDataGenerator"/> class, for the 
        /// specified scenario and reporting data.
        /// </summary>
        /// <inheritdoc cref="ReportDataGenerator(Scenario, ReportingData, ModelingSettings)" path="/param"/>
        public VehiclesBatteryMotorReportDataGenerator(Scenario scen, ReportingData data, ModelingSettings settings) 
            : base(scen, data, settings) { }

        /// <inheritdoc/>
        protected override bool WriteYearTotals => false;

        private IVehicleRevision _vehData;

        /// <inheritdoc/>
        protected override IEnumerator<object[]> GetYearEnumerator(int? year)
        {
            foreach (var veh in this.Data.ScenarioData.Vehicles) {
                int yearValue = year.Value;
                this._vehData = veh.GetRevision(year);
                yield return this.GetValues(yearValue);
            }
        }

        private object[] GetValues(int year)
        {
            this.ClearBuffer();

            this.AppendHeaderValues(year);
            this.AppendGeneralInfo();
            this.AppendMotorAndBatteryInfo();
            this.AppendTechKeyInfo();

            return this.GetBuffer();
        }

        private void AppendHeaderValues(int year)
        {
            this.AppendBuffer(this.Scenario.Index);
            this.AppendBuffer(StringHelper.GetTitleCase(this.Scenario.Description));
            this.AppendBuffer(year.ToString());
            this.AppendBuffer(StringHelper.GetTitleCase(this._vehData.ManufacturerName, 4));
        }

        private void AppendGeneralInfo()
        {
            string powerTrain = this._vehData.HevType == HEVType.Conventional 
                ? "CONV" 
                : this._vehData.HevType.ToString(getAbbr: true);
            this.AppendBuffer(this._vehData.Code);
            AppendComponentCode(this._vehData.PlatformCode);
            AppendComponentCode(this._vehData.EngineCode);
            AppendComponentCode(this._vehData.TransmissionCode);
            this.AppendBuffer(powerTrain);
            this.AppendBuffer(this._vehData.TechnologyClass);

            void AppendComponentCode(int code)
            {
                if (code > 0) {
                    this.AppendBuffer(code);
                }
                else {
                    this.AppendEmpty(1);
                }
            }
        }

        private void AppendMotorAndBatteryInfo()
        {
            var simResult = SimulationDatabase.GetValue(this._vehData.TechKey);
            var techClass = this._vehData.TechnologyClass;

            this.AppendBuffer(simResult.GetBatteryCost(techClass));
            this.AppendBuffer(simResult.GetBatteryEnergy(techClass));
            this.AppendBuffer(simResult.GetMotor1PeakPower(techClass));
            this.AppendBuffer(simResult.GetMotor1ContPower(techClass));
            this.AppendBuffer(simResult.GetMotor2PeakPower(techClass));
            this.AppendBuffer(simResult.GetMotor2ContPower(techClass));
        }

        private void AppendTechKeyInfo()
        {
            this.AppendBuffer(TI.KeyToString(this._vehData.BaselineInfo.TechKey));
            this.AppendBuffer(TI.KeyToString(this._vehData.TechKey));
        }

    }
}
