using System;
using TechKey = Volpe.Cafe.TechKeys.TechKey128;

namespace Volpe.Cafe
{
    partial class TechnologyIndexes
    {
        /// <summary>
        /// Describes a predefined technology.
        /// </summary>
        [Serializable]
        public class TechnologyDefinition
        {
            //----- Constructors -----
            /// <summary>
            /// Initializes a new <see cref="TechnologyDefinition"/> instance.
            /// </summary>
            internal TechnologyDefinition(string name, int index, TechnologyFlags flags)
            {
                this.Name    = name;
                this.Index   = index;
                this.Pathway = (TechnologyPathways)flags & TechnologyPathways.All;
                this.Flags   = flags;
                //
                this.TechSupersedes = TechKey.Empty;
                this.TechDisables   = TechKey.Empty;
            }

            //----- Properties -----
            /// <summary>Gets the name of a technology.</summary>
            public string Name { get; private set; }
            /// <summary>Gets the unique zero-based index of a technology.</summary>
            public int Index { get; private set; }
            /// <summary>Gets the pathway on which the technology is evaluated.</summary>
            public TechnologyPathways Pathway { get; private set; }
            /// <summary>Gets the descriptive flags of a technology.</summary>
            TechnologyFlags Flags { get; set; }

            /// <summary>Gets a key representing zero or more technologies superseded by this technology.</summary>
            public TechKey TechSupersedes { get; private set; }
            /// <summary>Gets a key representing zero or more technologies disabled by this technology.</summary>
            public TechKey TechDisables { get; private set; }

            //-----  Methods -----
            /// <summary>
            /// Determines whether the specified technology flag is set on this technology definition.
            /// </summary>
            /// <param name="flag">The technology flag to check.</param>
            /// <returns>
            /// true, if the specified technology flag is set on this technology definition; false, otherwise.
            /// </returns>
            internal bool IsFlagSet(TechnologyFlags flag)
            {
                return ((this.Flags & flag) == flag);
            }
            /// <summary>
            /// Determines whether any of the specified technology flags are set on this technology definition.
            /// </summary>
            /// <param name="flags">The technology flags to check.</param>
            /// <returns>
            /// true, if any of the specified technology flags are set on this technology definition; false, otherwise.
            /// </returns>
            internal bool IsAnyFlagSet(TechnologyFlags flags)
            {
                TechnologyFlags partial = (this.Flags & flags);
                return partial != 0 && ((flags & partial) == partial);
            }
            /// <summary>
            /// Sets <see cref="TechSupersedes"/> and <see cref="TechDisables"/> tech-keys.
            /// </summary>
            internal void SetTechKeys(TechKey techSupersedes, TechKey techDisables)
            {
                this.TechSupersedes = techSupersedes;
                this.TechDisables = techDisables;
            }
        }

        /// <summary>
        /// Defines technology pathways assigned to a technology.
        /// </summary>
        [Serializable, Flags]
        public enum TechnologyPathways : ulong
        {
            //--- engine pathways ---
            /// <summary>Defines an Engine Configuration pathway.</summary>
            EngineConfigurationPath     = TechnologyFlags.EngineConfigurationPath,
            /// <summary>Defines a Basic Engine pathway.</summary>
            BasicEnginePath             = TechnologyFlags.BasicEnginePath,
            /// <summary>Defines a Turbocharged Engine pathway.</summary>
            TurboEnginePath             = TechnologyFlags.TurboEnginePath,
            /// <summary>Defines an Advanced DEAC Engine pathway.</summary>
            AdvDEACEnginePath           = TechnologyFlags.AdvDEACEnginePath,
            /// <summary>Defines a High Compression Ratio Engine pathway.</summary>
            HCREnginePath               = TechnologyFlags.HCREnginePath,
            /// <summary>Defines a Variable Compression Ratio Engine pathway.</summary>
            VCREnginePath               = TechnologyFlags.VCREnginePath,
            /// <summary>Defines a Variable Turbo Geometry Engine pathway.</summary>
            VTGEnginePath               = TechnologyFlags.VTGEnginePath,
            /// <summary>Defines an Advanced Turbo Engine pathway.</summary>
            AdvTurboEnginePath          = TechnologyFlags.AdvTurboEnginePath,
            /// <summary>Defines a Diesel Engine pathway.</summary>
            DieselEnginePath            = TechnologyFlags.DieselEnginePath,
            /// <summary>Defines an Alternative Fuel Engine pathway.</summary>
            AltFuelEnginePath           = TechnologyFlags.AltFuelEnginePath,

            //--- transmission pathways ---
            /// <summary>Defines an Automatic Transmission pathway.</summary>
            AutoTransmissionPath        = TechnologyFlags.AutoTransmissionPath,

            //--- vehicle (electirification/hev) pathways ---
            /// <summary>Defines an Electrification pathway.</summary>
            ElectrificationPath         = TechnologyFlags.ElectrificationPath,
            /// <summary>Defines a P2 Strong Hybrid/Electric Vehicle pathway, paired with a basic engine.</summary>
            HEVP2Path                   = TechnologyFlags.HEVP2Path,
            /// <summary>Defines a P2 Strong Hybrid/Electric Vehicle pathway, paired with a turbo engine.</summary>
            TurboP2Path                 = TechnologyFlags.TurboP2Path,
            /// <summary>Defines a P2 Strong Hybrid/Electric Vehicle pathway, paired with an HCR engine.</summary>
            HCRP2Path                   = TechnologyFlags.HCRP2Path,
            /// <summary>Defines a Power-split Strong Hybrid/Electric Vehicle pathway.</summary>
            HEVPSPath                   = TechnologyFlags.HEVPSPath,
            /// <summary>Defines a Plug-In Hybrid/Electric Vehicle pathway.</summary>
            PHEVPath                    = TechnologyFlags.PHEVPath,
            /// <summary>Defines an Electric Vehicle pathway.</summary>
            ElectricVehiclePath         = TechnologyFlags.ElectricVehiclePath,

            //--- vehicle (body-level) pathways ---
            /// <summary>Defines a Low Rolling Resistance Tires pathway.</summary>
            ROLLPath                    = TechnologyFlags.ROLLPath,
            /// <summary>Defines an Aerodynamic Improvements pathway.</summary>
            AEROPath                    = TechnologyFlags.AEROPath,

            //--- platform pathways ---
            /// <summary>Defines a Mass Reduction pathway.</summary>
            MRPath                      = TechnologyFlags.MRPath,

            //--- collections of multiple paths ---
            /// <summary>Specifies a collection of all advanced engine technology pathways.</summary>
            AdvancedEnginePathsCollection = TurboEnginePath | AdvDEACEnginePath | HCREnginePath |
                                            VCREnginePath | VTGEnginePath | AdvTurboEnginePath |
                                            DieselEnginePath | AltFuelEnginePath,
            /// <summary>Specifies a collection of all engine technology pathways.</summary>
            EnginePathsCollection = AdvancedEnginePathsCollection | EngineConfigurationPath | BasicEnginePath,

            /// <summary>Specifies a collection of all hybridization technology pathways.</summary>
            HybridizationPathsCollection = HEVP2Path | TurboP2Path | HCRP2Path | HEVPSPath,
            /// <summary>Specifies a collection of all hybrid/electric technology pathways.</summary>
            HybridElectricPathsCollection = HybridizationPathsCollection | PHEVPath | ElectricVehiclePath,

            //--- combination of paths by application-level ---
            /// <summary>Specifies a combination of all engine-level technology pathways.</summary>
            AllEngine = EnginePathsCollection,
            /// <summary>Specifies a combination of all transmission-level technology pathways.</summary>
            AllTransmission = AutoTransmissionPath,
            /// <summary>Specifies a combination of all vehicle-level technology pathways.</summary>
            AllVehicle = ElectrificationPath | HybridElectricPathsCollection | ROLLPath | AEROPath,
            /// <summary>Specifies a combination of all platform-level technology pathways.</summary>
            AllPlatform = MRPath,

            /// <summary>Specifies a combination of ALL technology pathways.</summary>
            All = AllEngine | AllTransmission | AllVehicle | AllPlatform
        }

        /// <summary>
        /// Provides configuration flags for a technology.
        /// </summary>
        [Serializable, Flags]
        internal enum TechnologyFlags : ulong
        {
            /// <summary>
            /// Specifies a technology does not have any flags. This is the initial state of an "empty" technology,
            /// however, it is not a valid state for technologies selected for modeling.
            /// </summary>
            None = 0,

            //--- technology paths ---
            EngineConfigurationPath     = 1UL << 0,
            BasicEnginePath             = 1UL << 1,
            TurboEnginePath             = 1UL << 2,
            AdvDEACEnginePath           = 1UL << 3,
            HCREnginePath               = 1UL << 4,
            VCREnginePath               = 1UL << 5,
            VTGEnginePath               = 1UL << 6,
            AdvTurboEnginePath          = 1UL << 7,
            DieselEnginePath            = 1UL << 8,
            AltFuelEnginePath           = 1UL << 9,
            AutoTransmissionPath        = 1UL << 10,
            ElectrificationPath         = 1UL << 11,
            HEVP2Path                   = 1UL << 12,
            TurboP2Path                 = 1UL << 13,
            HCRP2Path                   = 1UL << 14,
            HEVPSPath                   = 1UL << 15,
            PHEVPath                    = 1UL << 16,
            ElectricVehiclePath         = 1UL << 17,
            ROLLPath                    = 1UL << 18,
            AEROPath                    = 1UL << 19,
            MRPath                      = 1UL << 20,

            //--- app-level ---
            VehicleLevel                = 1UL << 32,
            PlatformLevel               = 1UL << 33,
          //NameplateLevel              = 1UL << 34,
          //PowertrainLevel             = 1UL << 35,
            EngineLevel                 = 1UL << 36,
            TransmissionLevel           = 1UL << 37,

            //--- app-schedule ---
            BaselineOnly                = 1UL << 40,
            RefreshBased                = 1UL << 41,
            RedesignBased               = 1UL << 42,

            //--- cost-basis ---
            CostPerPound                = 1UL << 43,
            CostPerCylinder             = 1UL << 44,
            CostPerBank                 = 1UL << 45,

            //--- powertrain/fuel-conversion ---
            C2Diesel                    = 1UL << 48,
            C2CNG                       = 1UL << 49,
            C2LNG                       = 1UL << 50,
            C2LPG                       = 1UL << 51,
            C2MHEV                      = 1UL << 52,
            C2SHEV                      = 1UL << 53,
            C2PHEV                      = 1UL << 54,
            C2EV                        = 1UL << 55,
            C2FCV                       = 1UL << 56,

            //--- other/misc flags ---
            /// <summary>
            /// Indicates whether a technology should be automatically applied to a vehicle as soon as it becomes
            /// available.
            /// </summary>
            ForcedApplication = 1UL << 61,
            /// <summary>
            /// Indicates whether a technology has battery costs defined in the vehicle simulation database.
            /// </summary>
            BatteryCostTech = 1UL << 62,
            /// <summary>
            /// Indicates whether a technology, when it is used on a vehicle, modifies vehicle-specific FCAdjKey.
            /// <br/><br/>
            /// <b>NOTE</b>:
            /// This flag is no longer applicable and is planned for removal.
            /// </summary>
            [Obsolete("This flag is no longer applicable and is planned for removal.", error: false)]
            FCAdjKey = 1UL << 63
        }
    }
}
