using System;

//----------------------------------------------------------------------------------------------//
// This file contains enumerations defining various engineering characteristics for vehicle,    //
// platform, engine, and transmission variables.                                                //
//                                                                                              //
// Since market data inputs include numerous vehicles, platforms, engines, and transmissions,   //
// to conserve memory, the enumerated types defined here should use the smallest possible       //
// primitive as its underlying type (e.g., sbyte rather than int). These types are expected to  //
// be sparsely used by the model; thus, no performance penalty is expected.                     //
//----------------------------------------------------------------------------------------------//
namespace Volpe.Cafe.MarketData
{
    #region <<< Transmission-specific enums >>>

    /// <summary>
    /// Specifies a vehicle transmission's type.
    /// </summary>
    [Serializable]
    public enum TransmissionType : sbyte
    {
        /// <summary>Specifies that the vehicle transmission's type is unknown or undefined.</summary>
        None = 0,

        /// <summary>Specifies a manual transmission.</summary>
        M,
        /// <summary>Specifies an automatic transmission.</summary>
        A,
        /// <summary>Specifies a continuously variable transmission (CVT).</summary>
        CVT,
        /// <summary>Specifies an automated manual transmission (AMT).</summary>
        AMT,
        /// <summary>Specifies a dual-clutch transmission (DCT).</summary>
        DCT
    }

    #endregion

    #region <<< Engine-specific enums >>>

    /// <summary>
    /// Specifies a vehicle engine's configuration.
    /// </summary>
    [Serializable]
    public enum EngineConfiguration : sbyte
    {
        /// <summary>Specifies that the vehicle engine's configuration is unknown or undefined.</summary>
        None = 0,

        /// <summary>Specifies an inline engine configuration.</summary>
        I,
        /// <summary>Specifies a V engine configuration.</summary>
        V,
        /// <summary>Specifies an H engine configuration.</summary>
        H,
        /// <summary>Specifies a W engine configuration.</summary>
        W,
        /// <summary>Specifies a rotary engine configuration.</summary>
        R
    }

    /// <summary>
    /// Specifies the vehicle engine's cycle.
    /// </summary>
    [Serializable]
    public enum EngineCycle : sbyte
    {
        /// <summary>Specifies that the vehicle engine's cycle is unknown or undefined.</summary>
        None = 0,

        /// <summary>Specifies an Otto cycle engine.</summary>
        Otto,
        /// <summary>Specifies an Atkinson cycle engine.</summary>
        Atkinson,
        /// <summary>Specifies a Diesel cycle engine.</summary>
        Diesel
    }

    /// <summary>
    /// Specifies the vehicle engine's fuel delivery system.
    /// </summary>
    [Serializable]
    public enum EngineFuelSystem : sbyte
    {
        /// <summary>Specifies that the vehicle engine's fuel delivery system is unknown or undefined.</summary>
        None = 0,

        /// <summary>Specifies a sequential injection fuel delivery system.</summary>
        SFI,
        /// <summary>Specifies a Multiport injection fuel delivery system.</summary>
        MPFI,
        /// <summary>Specifies a gasoline direct injection fuel delivery system for gasoline engines.</summary>
        GDI,
        /// <summary>
        /// Specifies a Stoichiometric gasoline direct injection fuel delivery system for gasoline engines.
        /// </summary>
        SGDI,
        /// <summary>Specifies a Common Rail direct injection fuel delivery system for diesel engines.</summary>
        CRDI
    }

    /// <summary>
    /// Specifies the vehicle engine's aspiration.
    /// </summary>
    [Serializable]
    public enum EngineAspiration : sbyte
    {
        /// <summary>Specifies that the vehicle engine's aspiration is unknown or undefined.</summary>
        None = 0,

        /// <summary>Specifies a naturally aspirated engine.</summary>
        NaturallyAspirated,
        /// <summary>Specifies a supercharged engine.</summary>
        Supercharger,
        /// <summary>Specifies a turbocharged engine.</summary>
        Turbocharger
    }

    /// <summary>
    /// Specifies the vehicle engine's valvetrain design.
    /// </summary>
    [Serializable]
    public enum EngineValvetrain : sbyte
    {
        /// <summary>Specifies that the vehicle engine's valvetrain design is unknown or undefined.</summary>
        None = 0,

        /// <summary>Specifies an overhead valve engine.</summary>
        OHV,
        /// <summary>Specifies a single overhead camshaft engine.</summary>
        SOHC,
        /// <summary>Specifies a dual overhead camshaft engine.</summary>
        DOHC
    }

    /// <summary>
    /// Specifies the vehicle engine's valve timing.
    /// </summary>
    [Serializable]
    public enum EngineValveTiming : sbyte
    {
        /// <summary>Specifies that the vehicle engine's valve timing is unknown or undefined.</summary>
        None = 0,

        /// <summary>Specifies a fixed valve timing engine.</summary>
        Fixed,
        /// <summary>Specifies a variable valve timing engine.</summary>
        Variable,
        /// <summary>Specifies a variable valve timing engine.</summary>
        ICP,
        /// <summary>Specifies a variable valve timing engine.</summary>
        DCP,
        /// <summary>Specifies a variable valve timing engine.</summary>
        CCP
    }

    /// <summary>
    /// Specifies the vehicle engine's valve lift.
    /// </summary>
    [Serializable]
    public enum EngineValveLift : sbyte
    {
        /// <summary>Specifies that the vehicle engine's valve lift is unknown or undefined.</summary>
        None = 0,

        /// <summary>Specifies a fixed valve lift engine.</summary>
        Fixed,
        /// <summary>Specifies a variable valve lift engine.</summary>
        Variable
    }

    #endregion

    #region <<< Vehicle-specific enums >>>

    /// <summary>
    /// Specifies the vehicle's main structure of the chasis.
    /// </summary>
    [Serializable]
    public enum VehicleFrame : sbyte
    {
        /// <summary>Specifies that the vehicle's frame is unknown or undefined.</summary>
        None = 0,

        /// <summary>Specifies a ladder frame construction vehicle.</summary>
        Ladder,
        /// <summary>Specifies a unibody construction vehicle.</summary>
        Unibody
    }

    /// <summary>
    /// Specifies the vehicle's drive type.
    /// </summary>
    [Serializable]
    public enum DriveType : sbyte
    {
        /// <summary>Specifies that the vehicle's drive is unknown or undefined.</summary>
        None = 0,

        /// <summary>Specifies a front-wheel drive vehicle.</summary>
        FWD,
        /// <summary>Specifies a rear-wheel drive vehicle.</summary>
        RWD,
        /// <summary>Specifies an all-wheel drive vehicle.</summary>
        AWD,
        /// <summary>Specifies a four-wheel drive vehicle.</summary>
        x4WD
    }

    #endregion

    #region <<< Common enums >>>

    /// <summary>
    /// Specifies whether the vehicle, engine, or transmission is produced domestically or is imported.
    /// </summary>
    [Serializable]
    public enum Origin : sbyte
    {
        /// <summary>Specifies a domestically produced vehicle, engine, or transmission.</summary>
        Domestic = 0,
        /// <summary>Specifies an imported vehicle, engine, or transmission.</summary>
        Imported = 1
    }

    #endregion

    #region <<< Helper Classes >>>

    /// <summary>
    /// Provides extension methods for various enumerations.
    /// </summary>
    [Serializable]
    public static class EnumExtensions
    {
        /// <summary>
        /// Determines whether the specified <see cref="TransmissionType"/> instance represents a sequential
        /// transmission type. That is, one of: <see cref="TransmissionType.DCT"/> or 
        /// <see cref="TransmissionType.AMT"/>.
        /// </summary>
        public static bool IsSequential(this TransmissionType src)
        {
            return src == TransmissionType.DCT || src == TransmissionType.AMT;
        }
        /// <summary>
        /// Determines whether the specified <see cref="TransmissionType"/> instance is a continously variable
        /// transmission (<see cref="TransmissionType.CVT"/>).
        /// </summary>
        public static bool IsCVT(this TransmissionType src)
        {
            return (src == TransmissionType.CVT);
        }
        /// <summary>
        /// Determines whether the specified <see cref="TransmissionType"/> instance is an automatic transmission
        /// (<see cref="TransmissionType.A"/>).
        /// </summary>
        public static bool IsAutomatic(this TransmissionType src)
        {
            return (src == TransmissionType.A);
        }
        /// <summary>
        /// Determines whether the specified <see cref="TransmissionType"/> instance is a manual transmission
        /// (<see cref="TransmissionType.M"/>).
        /// </summary>
        public static bool IsManual(this TransmissionType src)
        {
            return (src == TransmissionType.M);
        }

        /// <summary>
        /// Converts the specified <see cref="EngineAspiration"/> value to its equivalent string representation,
        /// optionally using the associated abbreviations.
        /// </summary>
        /// <param name="src">The <see cref="EngineAspiration"/> value to convert.</param>
        /// <param name="getAbbr">true, to return engine aspiration abbreviations; false, to return full names.</param>
        /// <returns>A string equivalent of the <see cref="EngineAspiration"/> value.</returns>
        public static string ToString(this EngineAspiration src, bool getAbbr = false)
        {
            if (!getAbbr)
                return src.ToString();

            switch (src)
            {
                case EngineAspiration.NaturallyAspirated: return "NA";
                case EngineAspiration.Supercharger      : return "S";
                case EngineAspiration.Turbocharger      : return "T";

                default:
                    return src.ToString();
            }
        }

        /// <summary>
        /// Determines the number of banks associated with the specified <see cref="EngineConfiguration"/>.
        /// </summary>
        public static int GetNumberOfBanks(this EngineConfiguration src)
        {
            switch (src)
            {
                case EngineConfiguration.I:
                case EngineConfiguration.R: return 1;
                case EngineConfiguration.V:
                case EngineConfiguration.H: return 2;
                case EngineConfiguration.W: return 4;

                default:
                    return 0;
            }
        }

        /// <summary>
        /// Determines whether the specified <see cref="EngineValveTiming"/> instance is
        /// <see cref="EngineValveTiming.Fixed"/>.
        /// </summary>
        public static bool IsFixed(this EngineValveTiming src)
        {
            return (src == EngineValveTiming.Fixed);
        }
        /// <summary>
        /// Determines whether the specified <see cref="EngineValveTiming"/> instance represents variable engine
        /// timing. That is, one of: <see cref="EngineValveTiming.Variable"/>, <see cref="EngineValveTiming.ICP"/>,
        /// <see cref="EngineValveTiming.DCP"/>, <see cref="EngineValveTiming.CCP"/>.
        /// </summary>
        public static bool IsVariable(this EngineValveTiming src)
        {
            return src != EngineValveTiming.Fixed
                && src != EngineValveTiming.None;
        }

        /// <summary>
        /// Determines whether the specified <see cref="EngineValveLift"/> instance is
        /// <see cref="EngineValveLift.Fixed"/>.
        /// </summary>
        public static bool IsFixed(this EngineValveLift src)
        {
            return (src == EngineValveLift.Fixed);
        }
        /// <summary>
        /// Determines whether the specified <see cref="EngineValveLift"/> instance is
        /// <see cref="EngineValveLift.Variable"/>.
        /// </summary>
        public static bool IsVariable(this EngineValveLift src)
        {
            return (src == EngineValveLift.Variable);
        }
    }

    #endregion
}
