#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member

using System;
using System.Collections.Generic;

using Volpe.Cafe.Initializers;
using Volpe.Cafe.MarketData.Design;
using Volpe.Cafe.TechAnalysis;

using TechKey = Volpe.Cafe.TechKeys.TechKey128;

namespace Volpe.Cafe.MarketData.BaselineInfo
{
    /// <summary>
    /// Provides a description of baseline engineering characteristics for a vehicle.
    /// </summary>
    /// <seealso cref="IVehicle"/>
    [Serializable]
    public sealed class BaselineVehicle : IVehicleInfo
    {
        #region <<< Constructors >>>

        /// <summary>
        /// Initializes a new instance of the <see cref="BaselineVehicle"/> class.
        /// </summary>
        public BaselineVehicle(Dictionary<string, object> values)
        {
            DataObjectInitializer.SetPropertyValues(this, values);

            // baseline tech-key must be assigned from used-techs
            this.TechKey = KeyInitializer.CalcBaselineTechKey(this);
        }

        #endregion

        #region <<< Properties >>>

        /// <summary>
        /// Gets the unique code assigned to the vehicle.
        /// </summary>
        public int Code { get; private set; }
        /// <summary>
        /// Gets the name of the manufacturer that produces the vehicle.
        /// </summary>
        public string ManufacturerName { get; private set; }

        //----- general vehicle info -----
        public string Brand { get; private set; }
        public string Model { get; private set; }
        public string Nameplate { get; private set; }

        public int PlatformCode { get; private set; }
        public int EngineCode { get; private set; }
        public int TransmissionCode { get; private set; }

        //----- fuel-economy values -----
        public FuelValue FuelEconomy { get; private set; }
        public FuelValue FuelShare { get; private set; }
        public FuelType FuelType => this.FuelShare.FuelType;

        //----- sales/msrp -----
        /// <summary>
        /// Gets the vehicle's forecast of sales during the baseline model year.
        /// </summary>
        public double Sales { get; private set; }
        /// <summary>
        /// Gets the vehicle's manufacturer suggested retail price (MSRP) during the baseline model year.
        /// </summary>
        public double Msrp { get; private set; }

        //----- regulatory classification -----
        public RegulatoryClass RegClass { get; private set; }
        /// <summary>
        /// Gets the vehicle's secondary CAFE regulatory class assignment, which takes effect during a future year if 
        /// the vehicle is reclassified.
        /// </summary>
        public RegulatoryClass RegClass2 { get; private set; }
        public SafetyClass SafetyClass { get; private set; }
        public VehicleClass VehicleClass { get; private set; }

        public TechnologyClass TechnologyClass { get; private set; }
        public EngineTechnologyClass EngineTechnologyClass { get; private set; }

        public bool IsZevCandidate => this.ZEVCandidate.HasValue;
        public int? ZEVCandidate { get; private set; }
        public int ZevApplicationYear { get; private set; }
        public int ZevReferenceVehicleCode { get; private set; }

        public bool CARBAgreement { get; private set; }

        //----- vehicle characteristics -----
        public Origin Origin { get; private set; }

        public VehicleStyle Style { get; private set; }
        public VehicleFrame Structure { get; private set; }
        public DriveType Drive { get; private set; }

        public double Footprint { get; private set; }

        public double CurbWeightMR0 { get; private set; }
        public double CurbWeight { get; private set; }
        public double GVWR { get; private set; }
        public double GCWR { get; private set; }

        public double FuelCapacity { get; private set; }

        /// <summary>
        /// Gets the maximum ratio of GVWR to Curb Weight allowed for the vehicle.
        /// </summary>
        public double MaxGVWRToCW { get; private set; }
        /// <summary>
        /// Gets the maximum ratio of GCWR to GVWR allowed for the vehicle.
        /// </summary>
        public double MaxGCWRToGVWR { get; private set; }

        //----- vehicle powertrain -----
        /// <summary>
        /// Gets whether the vehicle uses a conventional or a hybrid/electric powertrain.
        /// </summary>
        public HEVType HevType { get; private set; }

        /// <summary>
        /// Gets the combined power produced by the vehicle's powertrain, including engine and motor.
        /// </summary>
        public double VehiclePower { get; private set; }
        /// <summary>
        /// Gets the combined torque produced by the vehicle's powertrain, including engine and motor.
        /// </summary>
        public double VehicleTorque { get; private set; }
        /// <summary>
        /// Gets the maximum distance, in miles, the vehicle may travel when operating on all of its available fuel
        /// sources.
        /// </summary>
        public double VehicleRange { get; private set; }

        //----- planning & assembly -----
        /// <summary>
        /// Gets the list of model years representing when the vehicle is refreshed.
        /// </summary>
        public ModelYearKey RefreshYears { get; private set; }
        /// <summary>
        /// Gets the list of model years representing when the vehicle is redesigned.
        /// </summary>
        public ModelYearKey RedesignYears { get; private set; }

        /// <summary>
        /// Gets the average employment hours originating at US dealerships for a single unit of the vehicle.
        /// </summary>
        public double DealershipHours { get; private set; }
        /// <summary>
        /// Gets the average employment hours associated with US assembly and manufacturing of a single unit of the
        /// vehicle.
        /// </summary>
        public double USAssemblyHours { get; private set; }
        /// <summary>
        /// Gets the percentage of vehicle's content (parts and labor) originating in the US.
        /// </summary>
        public double PercentUSContent { get; private set; }

        //----- technology utilization -----
        /// <summary>
        /// Gets the list of technologies initially used on the vehicle.
        /// </summary>
        public TechKey UsedTechnologies { get; private set; }
        /// <summary>
        /// Gets the list of technologies available for application on the vehicle.
        /// </summary>
        public TechKey AvailableTechnologies { get; private set; }

        /// <summary>
        /// Gets the aggregate list of technologies initially used on the vehicle, which includes the used technologies
        /// state from the vehicle itself, as well as the used states from the vehicle's platform, engine, and
        /// transmission (whichever available).
        /// </summary>
        public TechKey UsedTechnologiesFull { get; private set; }
        /// <summary>
        /// Gets the aggregate list of technologies available for application on the vehicle, which includes the
        /// available technologies state from the vehicle itself, as well as the available states from the vehicle's
        /// platform, engine, and transmission (whichever available).
        /// </summary>
        public TechKey AvailableTechnologiesFull { get; private set; }

        /// <summary>
        /// Gets the technology key, representing the baseline technology configuration associated with the vehicle.
        /// </summary>
        /// <remarks>
        /// <b>NOTE</b>:
        /// The baseline technology key is a derived value, which is not parsed from the input data and must not be
        /// assigned by the input parser. Instead, this value will be computed and assigned by the constructor based on
        /// the value of the <see cref="UsedTechnologiesFull"/> property.
        /// <br/><br/>
        /// The <see cref="TechKey"/> may not necessarily be the same as <see cref="UsedTechnologiesFull"/>. While
        /// <see cref="UsedTechnologiesFull"/> identifies the technologies selected as used on a vehicle (and its
        /// platform, engine, and transmission) by the user, the <see cref="TechKey"/> represents the same technology
        /// configuration, but with the possible conflicts, redundancies, and dependencies resolved.
        /// </remarks>
        public TechKey TechKey { get; }

        //----- "derived"/auto-computed vehicle characteristics -----
        /// <summary>
        /// Gets the payload capacity of the vehicle, which is computed as GVWR - Curb Weight.
        /// </summary>
        public double PayloadCapacity => this.GVWR - this.CurbWeight;
        /// <summary>
        /// Gets the towing capacity of the vehicle, which is computed as GCWR - GVWR.
        /// </summary>
        public double TowingCapacity => this.GCWR - this.GVWR;
        /// <summary>
        /// Gets the loaded vehicle weight, which is computed as Curb Weight + 300 lbs.
        /// </summary>
        public double LVW => this.CurbWeight + 300;
        /// <summary>
        /// Gets the adjusted loaded vehicle weight, which is computed as (Curb Weight + GVWR) / 2.
        /// </summary>
        public double ALVW => (this.CurbWeight + this.GVWR) / 2;

        #endregion

        #region <<< Methods >>>

        /// <summary>
        /// Returns the string representation of this <see cref="BaselineVehicle"/> instance.
        /// </summary>
        /// <returns>The string representation of the <see cref="BaselineVehicle"/> instance.</returns>
        public override string ToString()
        {
            return $"{this.Model} (Code: {this.Code}, " +
                   $"Plt: {this.PlatformCode}, Eng: {this.EngineCode}, Trn: {this.TransmissionCode})";
        }

        #endregion
    }
}
