#region <<< Using Directives >>>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

using Volpe.Cafe.Utils;

using TechKey = Volpe.Cafe.TechKeys.TechKey128;
#endregion

namespace Volpe.Cafe
{
    /// <summary>
    /// Provides information for the various known vehicle technologies.
    /// </summary>
    [Serializable]
    public static partial class TechnologyIndexes
    {
        #region <<< Constructors >>>

        static TechnologyIndexes()
        {
            // initialize technology definitions and bind to known variables
            TechnologyDefinitions = InitializeTechnologyDefinitions();
            TechnologyCount       = BindTechnologyIndexes();

            if (TechnologyCount != TechnologyDefinitions.Count) {
                ThrowHelper.InternalModelError();
            }

            for (int i = 0; i < TechnologyCount; i++) {
                if (i != TechnologyDefinitions[i].Index) {
                    // TechnologyDefinitions must be initialized such that each
                    // element in the list corresponds positionally to techIndex
                    ThrowHelper.InternalModelError();
                }
            }

            // initialize supersedes/disables states for each tech
            InitializeTechKeys();

            // build dictionary of name/index pairs (needed for quick lookups)
            TechNamesDict = new Dictionary<string, int>(TechnologyDefinitions.Count);
            foreach (var techDefinition in TechnologyDefinitions) {
                TechNamesDict.Add(techDefinition.Name, techDefinition.Index);
            }

            AllTechnologies = TechNamesDict.Values.ToArray();
            TechNames       = TechNamesDict.Keys.ToArray();
            TechNamesCSV    = string.Join(",", TechNames);

            EngineLevel       = FilterTechnologies(TechnologyFlags.EngineLevel);
            TransmissionLevel = FilterTechnologies(TechnologyFlags.TransmissionLevel);
            PlatformLevel     = FilterTechnologies(TechnologyFlags.PlatformLevel);
            VehicleLevel      = FilterTechnologies(TechnologyFlags.VehicleLevel);

            TechNamesEngine       = FilterTechnologyNames(TechnologyFlags.EngineLevel);
            TechNamesTransmission = FilterTechnologyNames(TechnologyFlags.TransmissionLevel);
            TechNamesPlatform     = FilterTechnologyNames(TechnologyFlags.PlatformLevel);
            TechNamesVehicle      = FilterTechnologyNames(TechnologyFlags.VehicleLevel);
        }

        #endregion

        #region <<< Variables >>>

        #region < Declarations for each technology >

        /// <summary>Represents an engine-level technology on an Engine Configuration pathway.</summary>
        public static readonly int
            SOHC,
            DOHC;
        /// <summary>Represents an engine-level technology on a Basic Engine pathway.</summary>
        public static readonly int
            VVL,
            SGDI,
            DEAC;
        /// <summary>Represents an engine-level technology on a Turbocharged Engine pathway.</summary>
        public static readonly int
            TURBO0,
            TURBOE,
            TURBOD,
            TURBO1,
            TURBO2;
        /// <summary>Represents an engine-level technology on an Advanced DEAC Engine pathway.</summary>
        public static readonly int
            ADEACS,
            ADEACD;
        /// <summary>Represents an engine-level technology on a High Compression Ratio Engine pathway.</summary>
        public static readonly int
            HCR,
            HCRE,
            HCRD;
        /// <summary>Represents an engine-level technology on a Variable Compression Ratio Engine pathway.</summary>
        public static readonly int
            VCR;
        /// <summary>Represents an engine-level technology on a Variable Turbo Geometry Engine pathway.</summary>
        public static readonly int
            VTG,
            VTGE;
        /// <summary>Represents an engine-level technology on an Advanced Turbocharged Engine pathway.</summary>
        public static readonly int
            TURBOAD;
        /// <summary>Represents an engine-level technology on an Diesel Engine pathway.</summary>
        public static readonly int
            ADSL,
            DSLI;
        /// <summary>Represents an engine-level technology on an Alternative Fuel Engine pathway.</summary>
        public static readonly int
            CNG;
        /// <summary>Represents a transmission-level technology on an Automatic Transmission pathway.</summary>
        public static readonly int
            AT5,
            AT6,
            AT7L2,
            AT8,
            AT8L2,
            AT8L3,
            AT9L2,
            AT10L2,
            AT10L3,
            DCT6,
            DCT8,
            CVT,
            CVTL2;
        /// <summary>Represents a vehicle-level technology on an Electrification pathway.</summary>
        public static readonly int
            CONV,
            SS12V,
            BISG;
        /// <summary>Represents a vehicle-level technology on a P2 SHEV (paired with an basic engine) pathway.</summary>
        public static readonly int
            P2S,
            P2SGDIS,
            P2D,
            P2SGDID;
        /// <summary>Represents a vehicle-level technology on a P2 SHEV (paired with an turbo engine) pathway.</summary>
        public static readonly int
            P2TRB0,
            P2TRBE,
            P2TRB1,
            P2TRB2;
        /// <summary>Represents a vehicle-level technology on a P2 SHEV (paired with an HCR engine) pathway.</summary>
        public static readonly int
            P2HCR,
            P2HCRE;
        /// <summary>Represents a vehicle-level technology on a Power-split Strong Hybrid/Electric Vehicle pathway.</summary>
        public static readonly int
            SHEVPS;
        /// <summary>Represents a vehicle-level technology on a Plug-In Hybrid/Electric Vehicle pathway.</summary>
        public static readonly int
            PHEV20T,
            PHEV50T,
            PHEV20H,
            PHEV50H,
            PHEV20PS,
            PHEV50PS;
        /// <summary>Represents a vehicle-level technology on an Electric Vehicle pathway.</summary>
        public static readonly int
            BEV1,
            BEV2,
            BEV3,
            BEV4,
            FCV;
        /// <summary>Represents a vehicle-level technology on a Low Rolling Resistance Tires pathway.</summary>
        public static readonly int
            ROLL0,
            ROLL10,
            ROLL20,
            ROLL30;
        /// <summary>Represents a vehicle-level technology on a Aerodynamic Improvements pathway.</summary>
        public static readonly int
            AERO0,
            AERO5,
            AERO10,
            AERO15,
            AERO20;
        /// <summary>Represents a platform-level technology on a Mass Reduction pathway.</summary>
        public static readonly int
            MR0,
            MR1,
            MR2,
            MR3,
            MR4,
            MR5;

        #endregion

        /// <summary>Represents the total count of technologies available to the modeling system.</summary>
        public static readonly int TechnologyCount;

        /// <summary>Represents an array of technology indexes that are applicable to engines.</summary>
        public static readonly int[] EngineLevel;
        /// <summary>Represents an array of technology indexes that are applicable to transmissions.</summary>
        public static readonly int[] TransmissionLevel;
        /// <summary>Represents an array of technology indexes that are applicable to platforms.</summary>
        public static readonly int[] PlatformLevel;
        /// <summary>Represents an array of technology indexes that are applicable to vehicles.</summary>
        public static readonly int[] VehicleLevel;

        /// <summary>Represents an array of technology indexes for all supported technologies.</summary>
        public static readonly int[] AllTechnologies;

        /// <summary>Represents an array of engine-level technology names.</summary>
        public static readonly string[] TechNamesEngine;
        /// <summary>Represents an array of transmission-level technology names.</summary>
        public static readonly string[] TechNamesTransmission;
        /// <summary>Represents an array of platform-level technology names.</summary>
        public static readonly string[] TechNamesPlatform;
        /// <summary>Represents an array of vehicle-level technology names.</summary>
        public static readonly string[] TechNamesVehicle;

        /// <summary>Represents an array of technology names for all supported technologies.</summary>
        public static readonly string[] TechNames;
        /// <summary>Represents a string of all technology names in Comma Separated Values (CSV) format.</summary>
        public static readonly string TechNamesCSV;
        /// <summary>Represents a dictionary of technology name/index pairs.</summary>
        public static readonly Dictionary<string, int> TechNamesDict;

        /// <summary>
        /// Contains dynamically assigned definitions for all supported technologies. This list is then used as a
        /// building block for all other variables defined within this class.
        /// </summary>
        private static readonly List<TechnologyDefinition> TechnologyDefinitions;

        #endregion

        #region <<< Methods >>>

        /// <summary>
        /// Returns the index of a technology based on the specified name.
        /// </summary>
        /// <param name="name">The name of a technology.</param>
        /// <returns>The index of the technology with the specified name, or -1 if not found.</returns>
        public static int GetIndex(string name)
        {
            return TechNamesDict.TryGetValue(name.Trim(), out int index) ? index : -1;
        }

        /// <summary>
        /// Returns an array of indexes of the technologies based on the specified array of names.
        /// </summary>
        /// <param name="names">An array of technology names.</param>
        /// <returns>
        /// An array of indexes of the technology with the specified names. Any technology that could not be found will
        /// contain an index of -1.
        /// </returns>
        public static int[] GetIndexes(string[] names)
        {
            int[] indexes = new int[names.Length];
            for (int i = 0; i < names.Length; i++)
            {
                indexes[i] = GetIndex(names[i]);
            }
            return indexes;
        }

        /// <summary>
        /// Returns the name of a given technology based on the specified index.
        /// </summary>
        /// <param name="index">The index of a technology.</param>
        /// <returns>Technology name at index, or an empty string if index is out of range.</returns>
        public static string GetName(int index)
        {
            return (index < 0 || index >= TechnologyCount) ? string.Empty : TechNames[index];
        }

        /// <summary>
        /// Converts the specified technology key to an equivalent string representation
        /// </summary>
        /// <param name="key">The key to convert to a string.</param>
        /// <param name="delimiter">A character to use for delimiting technologies encapsulated by the key.</param>
        /// <returns>A string representation of a technology key.</returns>
        public static string KeyToString(TechKey key, char delimiter = ';')
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < TechnologyCount; i++)
            {
                TechnologyDefinition td = TechnologyDefinitions[i];
                if ((key & TechKey.Keys[td.Index]) == TechKey.Keys[td.Index])
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(delimiter);
                        sb.Append(' ');
                    }
                    sb.Append(td.Name);
                }
            }
            return sb.ToString();
        }

        /// <summary>
        /// Determines whether a technology with the specified index is within any of the specified technology paths.
        /// </summary>
        /// <param name="techIndex">The index of a technology to check.</param>
        /// <param name="paths">The technology paths to check.</param>
        /// <returns>
        /// true, if a technology with the specified index is within any of the specified technology paths;
        /// false, otherwise.
        /// </returns>
        public static bool IsAnyPathway(int techIndex, TechnologyPathways paths)
        {
            var techPath = GetTechPathway(techIndex);
            return (paths & techPath) == techPath;
        }

        #region < Methods for checking attributes of a technology >

        //--- get technology's path information ---
        /// <summary>Returns the technology pathway on which the technology with the specified index is evaluated.</summary>
        public static TechnologyPathways GetTechPathway(int index) { return TechnologyDefinitions[index].Pathway; }

        //--- get technology's supersedes/disables list ---
        /// <summary>Returns a key representing zero or more technologies superseded by the technology with the specified index.</summary>
        public static TechKey GetTechSupersedes(int index) { return TechnologyDefinitions[index].TechSupersedes; }
        /// <summary>Returns a key representing zero or more technologies disabled by the technology with the specified index.</summary>
        public static TechKey GetTechDisables(int index) { return TechnologyDefinitions[index].TechDisables; }
        
        //--- check technology's paths ---
        /// <summary>Returns whether the specified technology index is within the Engine Configuration pathway.</summary>
        public static bool IsEngineConfigurationPath(int index) { return CheckTechFlags(index, TechnologyFlags.EngineConfigurationPath); }
        /// <summary>Returns whether the specified technology index is within the Basic Engine pathway.</summary>
        public static bool IsBasicEnginePath        (int index) { return CheckTechFlags(index, TechnologyFlags.BasicEnginePath); }
        /// <summary>Returns whether the specified technology index is within the Turbocharged Engine pathway.</summary>
        public static bool IsTurboEnginePath        (int index) { return CheckTechFlags(index, TechnologyFlags.TurboEnginePath); }
        /// <summary>Returns whether the specified technology index is within the Advanced DEAC Engine pathway.</summary>
        public static bool IsAdvDEACEnginePath      (int index) { return CheckTechFlags(index, TechnologyFlags.AdvDEACEnginePath); }
        /// <summary>Returns whether the specified technology index is within the High Compression Ratio Engine pathway.</summary>
        public static bool IsHCREnginePath          (int index) { return CheckTechFlags(index, TechnologyFlags.HCREnginePath); }
        /// <summary>Returns whether the specified technology index is within the Variable Compression Ratio Engine pathway.</summary>
        public static bool IsVCREnginePath          (int index) { return CheckTechFlags(index, TechnologyFlags.VCREnginePath); }
        /// <summary>Returns whether the specified technology index is within the Variable Turbo Geometry Engine pathway.</summary>
        public static bool IsVTGEnginePath          (int index) { return CheckTechFlags(index, TechnologyFlags.VTGEnginePath); }
        /// <summary>Returns whether the specified technology index is within the Advanced Turbo Engine pathway.</summary>
        public static bool IsAdvTurboEnginePath     (int index) { return CheckTechFlags(index, TechnologyFlags.AdvTurboEnginePath); }
        /// <summary>Returns whether the specified technology index is within the Diesel Engine pathway.</summary>
        public static bool IsDieselEnginePath       (int index) { return CheckTechFlags(index, TechnologyFlags.DieselEnginePath); }
        /// <summary>Returns whether the specified technology index is within the Alternative Fuel Engine pathway.</summary>
        public static bool IsAltFuelEnginePath      (int index) { return CheckTechFlags(index, TechnologyFlags.AltFuelEnginePath); }
        /// <summary>Returns whether the specified technology index is within the Automatic Transmission pathway.</summary>
        public static bool IsAutoTransmissionPath   (int index) { return CheckTechFlags(index, TechnologyFlags.AutoTransmissionPath); }
        /// <summary>Returns whether the specified technology index is within the Electrification pathway.</summary>
        public static bool IsElectrificationPath    (int index) { return CheckTechFlags(index, TechnologyFlags.ElectrificationPath); }
        /// <summary>Returns whether the specified technology index is within the P2 SHEV (paired with an basic engine) pathway.</summary>
        public static bool IsHEVP2Path              (int index) { return CheckTechFlags(index, TechnologyFlags.HEVP2Path); }
        /// <summary>Returns whether the specified technology index is within the P2 SHEV (paired with an turbo engine) pathway.</summary>
        public static bool IsTurboP2Path            (int index) { return CheckTechFlags(index, TechnologyFlags.TurboP2Path); }
        /// <summary>Returns whether the specified technology index is within the P2 SHEV (paired with an HCR engine) pathway.</summary>
        public static bool IsHCRP2Path              (int index) { return CheckTechFlags(index, TechnologyFlags.HCRP2Path); }
        /// <summary>Returns whether the specified technology index is within the Power-split Strong Hybrid/Electric Vehicle pathway.</summary>
        public static bool IsHEVPSPath              (int index) { return CheckTechFlags(index, TechnologyFlags.HEVPSPath); }
        /// <summary>Returns whether the specified technology index is within the Plug-In Hybrid/Electric Vehicle pathway.</summary>
        public static bool IsPHEVPath               (int index) { return CheckTechFlags(index, TechnologyFlags.PHEVPath); }
        /// <summary>Returns whether the specified technology index is within the Electric Vehicle pathway.</summary>
        public static bool IsElectricVehiclePath    (int index) { return CheckTechFlags(index, TechnologyFlags.ElectricVehiclePath); }
        /// <summary>Returns whether the specified technology index is within the Low Rolling Resistance Tires pathway.</summary>
        public static bool IsROLLPath               (int index) { return CheckTechFlags(index, TechnologyFlags.ROLLPath); }
        /// <summary>Returns whether the specified technology index is within the Aerodynamic Improvements pathway.</summary>
        public static bool IsAEROPath               (int index) { return CheckTechFlags(index, TechnologyFlags.AEROPath); }
        /// <summary>Returns whether the specified technology index is within the Mass Reduction pathway.</summary>
        public static bool IsMassReductionPath      (int index) { return CheckTechFlags(index, TechnologyFlags.MRPath); }

        //--- check technology's paths collections ---
        /// <summary>Returns whether the specified technology index is within any of the Advanced Engine pathways.</summary>
        public static bool IsAdvancedEnginePathsCollection(int index) { return IsAnyPathway(index, TechnologyPathways.AdvancedEnginePathsCollection); }
        /// <summary>Returns whether the specified technology index is within any of the Hybridization pathways.</summary>
        public static bool IsHybridizationPathsCollection (int index) { return IsAnyPathway(index, TechnologyPathways.HybridizationPathsCollection); }
        /// <summary>Returns whether the specified technology index is within any of the Hybrid/Electric pathways.</summary>
        public static bool IsHybridElectricPathsCollection(int index) { return IsAnyPathway(index, TechnologyPathways.HybridElectricPathsCollection); }

        //--- check technology's application-level ---
        /// <summary>Returns whether the technology specified by the given index represents a vehicle-level technology.</summary>
        public static bool IsVehicleLevel     (int index) { return CheckTechFlags(index, TechnologyFlags.VehicleLevel); }
        /// <summary>Returns whether the technology specified by the given index represents a platform-level technology.</summary>
        public static bool IsPlatformLevel    (int index) { return CheckTechFlags(index, TechnologyFlags.PlatformLevel); }
        /// <summary>Returns whether the technology specified by the given index represents an engine-level technology.</summary>
        public static bool IsEngineLevel      (int index) { return CheckTechFlags(index, TechnologyFlags.EngineLevel); }
        /// <summary>Returns whether the technology specified by the given index represents a transmission-level technology.</summary>
        public static bool IsTransmissionLevel(int index) { return CheckTechFlags(index, TechnologyFlags.TransmissionLevel); }

        /// <summary>Returns whether the technology specified by the given index represents an engine-level or a transmission-level technology.</summary>
        public static bool IsEngineOrTransmissionLevel(int index) { return IsEngineLevel(index) || IsTransmissionLevel(index); }

        //--- check technology's application-schedule ---
        /// <summary>Returns whether the technology specified by the given index represents a baseline-only technology.</summary>
        public static bool IsBaselineOnly  (int index) { return CheckTechFlags(index, TechnologyFlags.BaselineOnly); }
        /// <summary>Returns whether the specified technology index is tied to vehicle's redesign schedule.</summary>
        public static bool IsTiedToRedesign(int index) { return CheckTechFlags(index, TechnologyFlags.RedesignBased); }
        /// <summary>Returns whether the specified technology index is tied to vehicle's refresh schedule.</summary>
        public static bool IsTiedToRefresh (int index) { return CheckTechFlags(index, TechnologyFlags.RefreshBased); }

        //--- check if technology has cost-basis ---
        /// <summary>Returns whether the specified technology index represents a material substitution technology.</summary>
        public static bool IsCostPerPound   (int index) { return CheckTechFlags(index, TechnologyFlags.CostPerPound); }
        /// <summary>Returns whether the specified technology index represents a technology whose costs are based on the number of engine cylinders.</summary>
        public static bool IsCostPerCylinder(int index) { return CheckTechFlags(index, TechnologyFlags.CostPerCylinder); }
        /// <summary>Returns whether the specified technology index represents a technology whose costs are based on engine configuration.</summary>
        public static bool IsCostPerBank    (int index) { return CheckTechFlags(index, TechnologyFlags.CostPerBank); }

        //--- check if technology is powertrain/fuel-conversion ---
        /// <summary>Returns whether the technology specified by the given index may convert a vehicle's engine to run a diesel.</summary>
        public static bool IsConversionToDiesel  (int index) { return CheckTechFlags(index, TechnologyFlags.C2Diesel); }
        /// <summary>Returns whether the technology specified by the given index may convert a vehicle's engine to run a compressed natural gas.</summary>
        public static bool IsConversionToCNG     (int index) { return CheckTechFlags(index, TechnologyFlags.C2CNG); }
        /// <summary> Returns whether the technology specified by the given index may convert a vehicle's engine to run a liquefied natural gas.</summary>
        public static bool IsConversionToLNG     (int index) { return CheckTechFlags(index, TechnologyFlags.C2LNG); }
        /// <summary>Returns whether the technology specified by the given index may convert a vehicle's engine to run a liquefied petroleum gas.</summary>
        public static bool IsConversionToLPG     (int index) { return CheckTechFlags(index, TechnologyFlags.C2LPG); }
        /// <summary>Returns whether the technology specified by the given index may convert a vehicle to a micro hybrid.</summary>
        public static bool IsConversionToMHEV    (int index) { return CheckTechFlags(index, TechnologyFlags.C2MHEV); }
        /// <summary>Returns whether the technology specified by the given index may convert a vehicle to a strong hybrid-electric vehicle (SHEV).</summary>
        public static bool IsConversionToSHEV    (int index) { return CheckTechFlags(index, TechnologyFlags.C2SHEV); }
        /// <summary>Returns whether the technology specified by the given index may convert a vehicle to a plug-in hybrid-electric vehicle (PHEV).</summary>
        public static bool IsConversionToPHEV    (int index) { return CheckTechFlags(index, TechnologyFlags.C2PHEV); }
        /// <summary>Returns whether the technology specified by the given index may convert a vehicle to a battery electric vehicle (BEV).</summary>
        public static bool IsConversionToEV      (int index) { return CheckTechFlags(index, TechnologyFlags.C2EV); }
        /// <summary>Returns whether the technology specified by the given index may convert a vehicle to a fuel cell vehicle (FCV).</summary>
        public static bool IsConversionToFCV     (int index) { return CheckTechFlags(index, TechnologyFlags.C2FCV); }
        /// <summary>Returns whether the technology specified by the given index may convert a vehicle to a battery electric vehicle (BEV) or to a fuel cell vehicle (FCV).</summary>
        public static bool IsConversionToBevOrFcv(int index) { return CheckAnyTechFlags(index, TechnologyFlags.C2EV | TechnologyFlags.C2FCV); }

        /// <summary>
        /// Returns whether the technology specified by the given index may convert a vehicle to a zero-emissions
        /// vehicle.
        /// </summary>
        public static bool IsConversionToZEV(int index)
        {
            return CheckAnyTechFlags(index, TechnologyFlags.C2PHEV | TechnologyFlags.C2EV | TechnologyFlags.C2FCV);
        }

        //--- check if technology is has other/misc flags ---
        /// <summary>Returns whether the specified technology index should be automatically applied to a vehicle.</summary>
        public static bool IsForcedApplication(int index) { return CheckTechFlags(index, TechnologyFlags.ForcedApplication); }
        /// <summary>Returns whether battery costs for the specified technology index are defined in the vehicle simulation database.</summary>
        public static bool IsBatteryCostTech(int index) { return CheckTechFlags(index, TechnologyFlags.BatteryCostTech); }

        //----- helper methods -----
        /// <summary>
        /// Determines whether the specified technology flag is set for a technology with the given index.
        /// </summary>
        /// <param name="techIndex">The index of a technology to check.</param>
        /// <param name="flag">The technology flag to check.</param>
        /// <returns>
        /// true, if the specified technology flag is set for a technology with the given index; false, otherwise.
        /// </returns>
        static bool CheckTechFlags(int techIndex, TechnologyFlags flag)
        {
            return TechnologyDefinitions[techIndex].IsFlagSet(flag);
        }
        /// <summary>
        /// Determines whether any of the specified technology flags are set for a technology with the given index.
        /// </summary>
        /// <param name="techIndex">The index of a technology to check.</param>
        /// <param name="flags">The technology flags to check.</param>
        /// <returns>
        /// true, if any of the specified technology flags are set for a technology with the given index;
        /// false, otherwise.
        /// </returns>
        static bool CheckAnyTechFlags(int techIndex, TechnologyFlags flags)
        {
            return TechnologyDefinitions[techIndex].IsAnyFlagSet(flags);
        }

        #endregion

        #region < Technology initialization methods -- must be called from constructor only!! >

        static List<TechnologyDefinition> InitializeTechnologyDefinitions()
        {
            List<TechnologyDefinition> techs = new List<TechnologyDefinition>();
            int index = 0;  // indexes start at 0
            //
            techs.Add(new TechnologyDefinition("SOHC",      index++, TechnologyFlags.EngineLevel | TechnologyFlags.BaselineOnly | TechnologyFlags.EngineConfigurationPath));
            techs.Add(new TechnologyDefinition("DOHC",      index++, TechnologyFlags.EngineLevel | TechnologyFlags.BaselineOnly | TechnologyFlags.EngineConfigurationPath));
            techs.Add(new TechnologyDefinition("VVL",       index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.CostPerCylinder | TechnologyFlags.BasicEnginePath));
            techs.Add(new TechnologyDefinition("SGDI",      index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.CostPerCylinder | TechnologyFlags.BasicEnginePath));
            techs.Add(new TechnologyDefinition("DEAC",      index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.BasicEnginePath));
            techs.Add(new TechnologyDefinition("TURBO0",    index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.TurboEnginePath));
            techs.Add(new TechnologyDefinition("TURBOE",    index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.TurboEnginePath));
            techs.Add(new TechnologyDefinition("TURBOD",    index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.TurboEnginePath));
            techs.Add(new TechnologyDefinition("TURBO1",    index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.TurboEnginePath));
            techs.Add(new TechnologyDefinition("TURBO2",    index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.TurboEnginePath));
            techs.Add(new TechnologyDefinition("ADEACS",    index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.AdvDEACEnginePath));
            techs.Add(new TechnologyDefinition("ADEACD",    index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.AdvDEACEnginePath));
            techs.Add(new TechnologyDefinition("HCR",       index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.HCREnginePath));
            techs.Add(new TechnologyDefinition("HCRE",      index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.HCREnginePath));
            techs.Add(new TechnologyDefinition("HCRD",      index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.HCREnginePath));
            techs.Add(new TechnologyDefinition("VCR",       index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.VCREnginePath));
            techs.Add(new TechnologyDefinition("VTG",       index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.VTGEnginePath));
            techs.Add(new TechnologyDefinition("VTGE",      index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.VTGEnginePath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("TURBOAD",   index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.AdvTurboEnginePath));
            techs.Add(new TechnologyDefinition("ADSL",      index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2Diesel | TechnologyFlags.DieselEnginePath));
            techs.Add(new TechnologyDefinition("DSLI",      index++, TechnologyFlags.EngineLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2Diesel | TechnologyFlags.DieselEnginePath));
            techs.Add(new TechnologyDefinition("CNG",       index++, TechnologyFlags.EngineLevel | TechnologyFlags.BaselineOnly | TechnologyFlags.C2CNG | TechnologyFlags.AltFuelEnginePath));
            techs.Add(new TechnologyDefinition("AT5",       index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.BaselineOnly | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("AT6",       index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.RefreshBased | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("AT7L2",     index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.BaselineOnly | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("AT8",       index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.RefreshBased | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("AT8L2",     index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.RefreshBased | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("AT8L3",     index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.RefreshBased | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("AT9L2",     index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.RefreshBased | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("AT10L2",    index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.RefreshBased | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("AT10L3",    index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.RefreshBased | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("DCT6",      index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.RefreshBased | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("DCT8",      index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.RefreshBased | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("CVT",       index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.BaselineOnly | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("CVTL2",     index++, TechnologyFlags.TransmissionLevel | TechnologyFlags.RefreshBased | TechnologyFlags.AutoTransmissionPath));
            techs.Add(new TechnologyDefinition("CONV",      index++, TechnologyFlags.VehicleLevel | TechnologyFlags.BaselineOnly | TechnologyFlags.ElectrificationPath));
            techs.Add(new TechnologyDefinition("SS12V",     index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2MHEV | TechnologyFlags.ElectrificationPath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("BISG",      index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2MHEV | TechnologyFlags.ElectrificationPath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("P2S",       index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2SHEV | TechnologyFlags.HEVP2Path | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("P2SGDIS",   index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2SHEV | TechnologyFlags.HEVP2Path | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("P2D",       index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2SHEV | TechnologyFlags.HEVP2Path | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("P2SGDID",   index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2SHEV | TechnologyFlags.HEVP2Path | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("P2TRB0",    index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2SHEV | TechnologyFlags.TurboP2Path | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("P2TRBE",    index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2SHEV | TechnologyFlags.TurboP2Path | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("P2TRB1",    index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2SHEV | TechnologyFlags.TurboP2Path | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("P2TRB2",    index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2SHEV | TechnologyFlags.TurboP2Path | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("P2HCR",     index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2SHEV | TechnologyFlags.HCRP2Path | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("P2HCRE",    index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2SHEV | TechnologyFlags.HCRP2Path | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("SHEVPS",    index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2SHEV | TechnologyFlags.HEVPSPath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("PHEV20T",   index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2PHEV | TechnologyFlags.PHEVPath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("PHEV50T",   index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2PHEV | TechnologyFlags.PHEVPath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("PHEV20H",   index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2PHEV | TechnologyFlags.PHEVPath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("PHEV50H",   index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2PHEV | TechnologyFlags.PHEVPath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("PHEV20PS",  index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2PHEV | TechnologyFlags.PHEVPath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("PHEV50PS",  index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2PHEV | TechnologyFlags.PHEVPath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("BEV1",      index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2EV | TechnologyFlags.ElectricVehiclePath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("BEV2",      index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2EV | TechnologyFlags.ElectricVehiclePath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("BEV3",      index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2EV | TechnologyFlags.ElectricVehiclePath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("BEV4",      index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2EV | TechnologyFlags.ElectricVehiclePath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("FCV",       index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.C2FCV | TechnologyFlags.ElectricVehiclePath | TechnologyFlags.BatteryCostTech));
            techs.Add(new TechnologyDefinition("ROLL0",     index++, TechnologyFlags.VehicleLevel | TechnologyFlags.BaselineOnly | TechnologyFlags.ROLLPath));
            techs.Add(new TechnologyDefinition("ROLL10",    index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RefreshBased | TechnologyFlags.ROLLPath));
            techs.Add(new TechnologyDefinition("ROLL20",    index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RefreshBased | TechnologyFlags.ROLLPath));
            techs.Add(new TechnologyDefinition("ROLL30",    index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RefreshBased | TechnologyFlags.ROLLPath));
            techs.Add(new TechnologyDefinition("AERO0",     index++, TechnologyFlags.VehicleLevel | TechnologyFlags.BaselineOnly | TechnologyFlags.AEROPath));
            techs.Add(new TechnologyDefinition("AERO5",     index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.AEROPath));
            techs.Add(new TechnologyDefinition("AERO10",    index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.AEROPath));
            techs.Add(new TechnologyDefinition("AERO15",    index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.AEROPath));
            techs.Add(new TechnologyDefinition("AERO20",    index++, TechnologyFlags.VehicleLevel | TechnologyFlags.RedesignBased | TechnologyFlags.AEROPath));
            techs.Add(new TechnologyDefinition("MR0",       index++, TechnologyFlags.PlatformLevel | TechnologyFlags.BaselineOnly | TechnologyFlags.MRPath));
            techs.Add(new TechnologyDefinition("MR1",       index++, TechnologyFlags.PlatformLevel | TechnologyFlags.RedesignBased | TechnologyFlags.CostPerPound | TechnologyFlags.MRPath));
            techs.Add(new TechnologyDefinition("MR2",       index++, TechnologyFlags.PlatformLevel | TechnologyFlags.RedesignBased | TechnologyFlags.CostPerPound | TechnologyFlags.MRPath));
            techs.Add(new TechnologyDefinition("MR3",       index++, TechnologyFlags.PlatformLevel | TechnologyFlags.RedesignBased | TechnologyFlags.CostPerPound | TechnologyFlags.MRPath));
            techs.Add(new TechnologyDefinition("MR4",       index++, TechnologyFlags.PlatformLevel | TechnologyFlags.RedesignBased | TechnologyFlags.CostPerPound | TechnologyFlags.MRPath));
            techs.Add(new TechnologyDefinition("MR5",       index++, TechnologyFlags.PlatformLevel | TechnologyFlags.RedesignBased | TechnologyFlags.CostPerPound | TechnologyFlags.MRPath));
            //
            return techs;
        }

        /// <summary>
        /// Dynamically assigns appropriate technology index to each "technology" variable (e.g., DOHC, AT8, SHEVPS)
        /// defined by this class, based on the "TechnologyDefinitions" list.
        /// </summary>
        static int BindTechnologyIndexes()
        {
            int techCount = 0;
            FieldInfo[] fields = typeof(TechnologyIndexes).GetFields();
            foreach (FieldInfo f in fields) {
                int index = TechnologyDefinitions.FindIndex(
                    item => StringHelper.Equals(item.Name, f.Name.TrimStart('_')));

                if (index != -1) {
                    f.SetValue(null, index);
                    techCount++;
                }
            }
            return techCount;
        }

        /// <summary>
        /// Initializes technology "supersedes" and "disables" lists.
        /// </summary>
        static void InitializeTechKeys()
        {
            //----------------------------------------------------------------------------------//
            // Initialize tech supersedes and disables tech-keys.                               //
            //----------------------------------------------------------------------------------//
            TechKey[] supersedes = new TechKey[TechnologyCount];
            TechKey[] disables   = new TechKey[TechnologyCount];
            for (int i = 0; i < TechnologyCount; i++)
            {
                supersedes[i] = TechKey.Empty;
                disables  [i] = TechKey.Empty;
            }

            //--------------------------------------------------
            //  ENGINE TECHNOLOGIES:
            //--------------------------------------------------
            //----- initialize Engine Configuration technologies -----
            disables  [SOHC    ] = TechKey.BuildKey(ADEACD, P2D, P2SGDID);
            disables  [DOHC    ] = TechKey.BuildKey(ADEACS, P2S, P2SGDIS);
            //----- initialize Basic Engine technologies -----
            // N/A
            //----- initialize Turbo Engine technologies -----
            supersedes[TURBO0  ] = BuildTechKey(TechnologyPathways.EngineConfigurationPath |
                                                TechnologyPathways.BasicEnginePath);
            supersedes[TURBOE  ] = 
            supersedes[TURBOD  ] = supersedes[TURBO0] | TechKey.BuildKey(TURBO0);
            supersedes[TURBO1  ] = supersedes[TURBO0] | TechKey.BuildKey(TURBO0, TURBOE, TURBOD);
            supersedes[TURBO2  ] = supersedes[TURBO1] | TechKey.BuildKey(TURBO1);
            //
            disables  [TURBO0  ] = 
            disables  [TURBO1  ] = 
            disables  [TURBO2  ] = BuildTechKey(TechnologyPathways.AdvDEACEnginePath |
                                                TechnologyPathways.HCREnginePath |
                                                TechnologyPathways.DieselEnginePath |
                                                TechnologyPathways.AltFuelEnginePath |
                                                (TechnologyPathways.HybridizationPathsCollection &
                                                ~TechnologyPathways.TurboP2Path),
                                                PHEV20H, PHEV50H, PHEV20PS, PHEV50PS);
            disables  [TURBOE  ] = disables[TURBO0] | TechKey.BuildKey(TURBOD);
            disables  [TURBOD  ] = disables[TURBO0] | TechKey.BuildKey(TURBOE);
            //----- initialize Advanced DEAC Engine technologies -----
            supersedes[ADEACS  ] = 
            supersedes[ADEACD  ] = BuildTechKey(TechnologyPathways.EngineConfigurationPath |
                                                TechnologyPathways.BasicEnginePath);
            //
            disables  [ADEACS  ] = 
            disables  [ADEACD  ] = BuildTechKey((TechnologyPathways.AdvancedEnginePathsCollection &
                                                ~TechnologyPathways.AdvDEACEnginePath &
                                                ~TechnologyPathways.AdvTurboEnginePath) |
                                                TechnologyPathways.HCRP2Path |
                                                TechnologyPathways.HEVPSPath);
            disables  [ADEACS  ] |= TechKey.BuildKey(ADEACD, P2D, P2SGDID);
            disables  [ADEACD  ] |= TechKey.BuildKey(ADEACS, P2S, P2SGDIS);
            //----- initialize HCR Engine technologies -----
            supersedes[HCR     ] = BuildTechKey(TechnologyPathways.EngineConfigurationPath |
                                                TechnologyPathways.BasicEnginePath);
            supersedes[HCRE    ] = 
            supersedes[HCRD    ] = supersedes[HCR] | TechKey.BuildKey(HCR);
            //                 
            disables  [HCR     ] = BuildTechKey((TechnologyPathways.AdvancedEnginePathsCollection &
                                                ~TechnologyPathways.HCREnginePath) |
                                                TechnologyPathways.HEVP2Path |
                                                TechnologyPathways.TurboP2Path,
                                                PHEV20T, PHEV50T);
            disables  [HCRE    ] = disables[HCR] | TechKey.BuildKey(HCRD);
            disables  [HCRD    ] = disables[HCR] | TechKey.BuildKey(HCRE);
            //----- initialize VCR Engine technologies -----
            supersedes[VCR     ] = BuildTechKey(TechnologyPathways.EngineConfigurationPath |
                                                TechnologyPathways.BasicEnginePath |
                                                TechnologyPathways.TurboEnginePath);
            disables  [VCR     ] = BuildTechKey((TechnologyPathways.AdvancedEnginePathsCollection &
                                                ~TechnologyPathways.VCREnginePath) |
                                                (TechnologyPathways.HybridizationPathsCollection &
                                                ~TechnologyPathways.TurboP2Path),
                                                PHEV20H, PHEV50H, PHEV20PS, PHEV50PS);
            //----- initialize VTG Engine technologies -----
            supersedes[VTG     ] = BuildTechKey(TechnologyPathways.EngineConfigurationPath |
                                                TechnologyPathways.BasicEnginePath |
                                                TechnologyPathways.TurboEnginePath);
            supersedes[VTGE    ] = supersedes[VTG] |
                                   BuildTechKey(TechnologyPathways.ElectrificationPath,
                                                VTG);
            //                 
            disables  [VTG     ] = 
            disables  [VTGE    ] = BuildTechKey((TechnologyPathways.AdvancedEnginePathsCollection &
                                                ~TechnologyPathways.VTGEnginePath) |
                                                (TechnologyPathways.HybridizationPathsCollection &
                                                ~TechnologyPathways.TurboP2Path),
                                                PHEV20H, PHEV50H, PHEV20PS, PHEV50PS);
            //----- initialize Advanced Turbo Engine technologies -----
            supersedes[TURBOAD ] = BuildTechKey(TechnologyPathways.EngineConfigurationPath |
                                                TechnologyPathways.BasicEnginePath |
                                                TechnologyPathways.TurboEnginePath |
                                                TechnologyPathways.AdvDEACEnginePath);
            disables  [TURBOAD ] = BuildTechKey((TechnologyPathways.AdvancedEnginePathsCollection &
                                                ~TechnologyPathways.AdvTurboEnginePath) |
                                                (TechnologyPathways.HybridizationPathsCollection &
                                                ~TechnologyPathways.TurboP2Path),
                                                PHEV20H, PHEV50H, PHEV20PS, PHEV50PS);
            //----- initialize Diesel Engine technologies -----
            supersedes[ADSL    ] = BuildTechKey(TechnologyPathways.EngineConfigurationPath |
                                                TechnologyPathways.BasicEnginePath);
            supersedes[DSLI    ] = supersedes[ADSL] | TechKey.BuildKey(ADSL);
            //                 
            disables  [ADSL    ] = 
            disables  [DSLI    ] = BuildTechKey((TechnologyPathways.AdvancedEnginePathsCollection &
                                                ~TechnologyPathways.DieselEnginePath) |
                                                (TechnologyPathways.HybridizationPathsCollection &
                                                ~TechnologyPathways.TurboP2Path),
                                                PHEV20H, PHEV50H, PHEV20PS, PHEV50PS); ;
            //----- initialize Alt Fuel Engine technologies -----
            supersedes[CNG     ] = BuildTechKey(TechnologyPathways.EngineConfigurationPath |
                                                TechnologyPathways.BasicEnginePath);
            disables  [CNG     ] = BuildTechKey(TechnologyPathways.All);

            //--------------------------------------------------
            //  TRANSMISSION TECHNOLOGIES:
            //--------------------------------------------------
            //----- initialize Automatic Transmission technologies -----
            supersedes[AT5     ] = TechKey.BuildKey();
            supersedes[AT6     ] = TechKey.BuildKey(AT5);
            supersedes[AT7L2   ] = TechKey.BuildKey(AT5, AT6);
            supersedes[AT8     ] = TechKey.BuildKey(AT5, AT6);
            supersedes[AT8L2   ] = TechKey.BuildKey(AT5, AT6, AT7L2, AT8);
            supersedes[AT8L3   ] = TechKey.BuildKey(AT5, AT6, AT7L2, AT8, AT8L2);
            supersedes[AT9L2   ] = TechKey.BuildKey(AT5, AT6, AT7L2, AT8, AT8L2);
            supersedes[AT10L2  ] = TechKey.BuildKey(AT5, AT6, AT7L2, AT8, AT8L2);
            supersedes[AT10L3  ] = TechKey.BuildKey(AT5, AT6, AT7L2, AT8, AT8L2, AT8L3, AT9L2, AT10L2);
            supersedes[DCT6    ] = TechKey.BuildKey(AT5);
            supersedes[DCT8    ] = TechKey.BuildKey(AT5, DCT6);
            supersedes[CVT     ] = TechKey.BuildKey(AT5);
            supersedes[CVTL2   ] = TechKey.BuildKey(AT5, AT6, AT8, CVT);
            //
            disables  [AT5     ] = TechKey.BuildKey(CVT);
            disables  [AT6     ] = TechKey.BuildKey(CVT, DCT6, DCT8);
            disables  [AT7L2   ] = TechKey.BuildKey(CVT, CVTL2, DCT6, DCT8, AT8);
            disables  [AT8     ] = TechKey.BuildKey(CVT, DCT6, DCT8, AT7L2);
            disables  [AT8L2   ] = TechKey.BuildKey(CVT, CVTL2, DCT6, DCT8);
            disables  [AT8L3   ] = TechKey.BuildKey(CVT, CVTL2, DCT6, DCT8, AT9L2, AT10L2);
            disables  [AT9L2   ] = TechKey.BuildKey(CVT, CVTL2, DCT6, DCT8, AT8L3, AT10L2);
            disables  [AT10L2  ] = TechKey.BuildKey(CVT, CVTL2, DCT6, DCT8, AT8L3, AT9L2);
            disables  [AT10L3  ] = TechKey.BuildKey(CVT, CVTL2, DCT6, DCT8);
            disables  [DCT6    ] = TechKey.BuildKey(CVT, CVTL2, AT6, AT7L2, AT8, AT8L2, AT8L3, AT9L2, AT10L2, AT10L3);
            disables  [DCT8    ] = TechKey.BuildKey(CVT, CVTL2, AT6, AT7L2, AT8, AT8L2, AT8L3, AT9L2, AT10L2, AT10L3);
            disables  [CVT     ] = TechKey.BuildKey(DCT6, DCT8, AT6, AT7L2, AT8, AT8L2, AT8L3, AT9L2, AT10L2, AT10L3);
            disables  [CVTL2   ] = TechKey.BuildKey(DCT6, DCT8, AT7L2, AT8L2, AT8L3, AT9L2, AT10L2, AT10L3);

            //--------------------------------------------------
            //  VEHICLE TECHNOLOGIES (HEVs):
            //--------------------------------------------------
            //----- initialize Electrification technologies -----
            supersedes[SS12V   ] = TechKey.BuildKey(CONV);
            supersedes[BISG    ] = TechKey.BuildKey(CONV, SS12V);
            //----- initialize HEV-P2 technologies -----
            supersedes[P2S     ] = 
            supersedes[P2D     ] = BuildTechKey(TechnologyPathways.EnginePathsCollection |
                                                TechnologyPathways.AutoTransmissionPath |
                                                TechnologyPathways.ElectrificationPath);
            supersedes[P2SGDIS ] = supersedes[P2S] | TechKey.BuildKey(P2S);
            supersedes[P2SGDID ] = supersedes[P2D] | TechKey.BuildKey(P2D);
            //
            disables  [P2S     ] = 
            disables  [P2SGDIS ] = BuildTechKey(TechnologyPathways.HybridizationPathsCollection &
                                               ~TechnologyPathways.HEVP2Path,
                                                P2D, P2SGDID);
            disables  [P2D     ] = 
            disables  [P2SGDID ] = BuildTechKey(TechnologyPathways.HybridizationPathsCollection &
                                               ~TechnologyPathways.HEVP2Path,
                                                P2S, P2SGDIS);
            //----- initialize Turbo-P2 technologies -----
            supersedes[P2TRB0  ] = BuildTechKey(TechnologyPathways.EnginePathsCollection |
                                                TechnologyPathways.AutoTransmissionPath |
                                                TechnologyPathways.ElectrificationPath);
            supersedes[P2TRBE  ] = supersedes[P2TRB0] | TechKey.BuildKey(P2TRB0);
            supersedes[P2TRB1  ] = supersedes[P2TRBE] | TechKey.BuildKey(P2TRBE);
            supersedes[P2TRB2  ] = supersedes[P2TRB1] | TechKey.BuildKey(P2TRB1);
            //                 
            disables  [P2TRB0  ] = 
            disables  [P2TRBE  ] = 
            disables  [P2TRB1  ] = 
            disables  [P2TRB2  ] = BuildTechKey(TechnologyPathways.HybridizationPathsCollection &
                                               ~TechnologyPathways.TurboP2Path,
                                                PHEV20H, PHEV50H, PHEV20PS, PHEV50PS);
            //----- initialize HCR-P2 technologies -----
            supersedes[P2HCR   ] = BuildTechKey(TechnologyPathways.EnginePathsCollection |
                                                TechnologyPathways.AutoTransmissionPath |
                                                TechnologyPathways.ElectrificationPath);
            supersedes[P2HCRE  ] = supersedes[P2HCR] | TechKey.BuildKey(P2HCR);
            //                 
            disables  [P2HCR   ] = 
            disables  [P2HCRE  ] = BuildTechKey(TechnologyPathways.HybridizationPathsCollection &
                                               ~TechnologyPathways.HCRP2Path,
                                                PHEV20T, PHEV50T, PHEV20PS, PHEV50PS);
            //----- initialize HEV-PS technologies -----
            supersedes[SHEVPS  ] = BuildTechKey(TechnologyPathways.EnginePathsCollection |
                                                TechnologyPathways.AutoTransmissionPath |
                                                TechnologyPathways.ElectrificationPath);
            disables  [SHEVPS  ] = BuildTechKey(TechnologyPathways.HybridizationPathsCollection &
                                               ~TechnologyPathways.HEVPSPath,
                                                PHEV20T, PHEV50T, PHEV20H, PHEV50H);
            //----- initialize PHEV technologies -----
            supersedes[PHEV20T ] = 
            supersedes[PHEV20H ] = 
            supersedes[PHEV20PS] = BuildTechKey(TechnologyPathways.EnginePathsCollection |
                                                TechnologyPathways.AutoTransmissionPath |
                                                TechnologyPathways.ElectrificationPath |
                                                TechnologyPathways.HybridizationPathsCollection);
            supersedes[PHEV50T ] = supersedes[PHEV20T] | TechKey.BuildKey(PHEV20T);
            supersedes[PHEV50H ] = supersedes[PHEV20H] | TechKey.BuildKey(PHEV20H);
            supersedes[PHEV50PS] = supersedes[PHEV20PS] | TechKey.BuildKey(PHEV20PS);
            //
            disables  [PHEV20T ] = 
            disables  [PHEV50T ] = TechKey.BuildKey(PHEV20H, PHEV50H, PHEV20PS, PHEV50PS);
            disables  [PHEV20H ] = 
            disables  [PHEV50H ] = TechKey.BuildKey(PHEV20T, PHEV50T, PHEV20PS, PHEV50PS);
            disables  [PHEV20PS] = 
            disables  [PHEV50PS] = TechKey.BuildKey(PHEV20T, PHEV50T, PHEV20H, PHEV50H);
            //----- initialize Electric Vehicle technologies -----
            supersedes[FCV     ] =
            supersedes[BEV1    ] = BuildTechKey(TechnologyPathways.EnginePathsCollection |
                                                TechnologyPathways.AutoTransmissionPath |
                                                TechnologyPathways.ElectrificationPath |
                                                TechnologyPathways.HybridizationPathsCollection |
                                                TechnologyPathways.PHEVPath);
            supersedes[BEV2    ] = supersedes[BEV1] | TechKey.BuildKey(BEV1);
            supersedes[BEV3    ] = supersedes[BEV2] | TechKey.BuildKey(BEV2);
            supersedes[BEV4    ] = supersedes[BEV3] | TechKey.BuildKey(BEV3);
            //
            disables  [BEV1    ] = TechKey.BuildKey(FCV);
            disables  [BEV2    ] = TechKey.BuildKey(FCV);
            disables  [BEV3    ] = TechKey.BuildKey(FCV);
            disables  [BEV4    ] = TechKey.BuildKey(FCV);
            disables  [FCV     ] = TechKey.BuildKey(BEV1, BEV2, BEV3, BEV4);

            //--------------------------------------------------
            //  VEHICLE/PLATFORM TECHNOLOGIES (BODY):
            //--------------------------------------------------
            //----- initialize ROLL technologies -----
            supersedes[ROLL10  ] = TechKey.BuildKey(ROLL0);
            supersedes[ROLL20  ] = TechKey.BuildKey(ROLL0, ROLL10);
            supersedes[ROLL30  ] = TechKey.BuildKey(ROLL0, ROLL10, ROLL20);
            //----- initialize AERO technologies -----
            supersedes[AERO5   ] = TechKey.BuildKey(AERO0);
            supersedes[AERO10  ] = TechKey.BuildKey(AERO0, AERO5);
            supersedes[AERO15  ] = TechKey.BuildKey(AERO0, AERO5, AERO10);
            supersedes[AERO20  ] = TechKey.BuildKey(AERO0, AERO5, AERO10, AERO15);
            //----- initialize MR technologies -----
            supersedes[MR1     ] = TechKey.BuildKey(MR0);
            supersedes[MR2     ] = TechKey.BuildKey(MR0, MR1);
            supersedes[MR3     ] = TechKey.BuildKey(MR0, MR1, MR2);
            supersedes[MR4     ] = TechKey.BuildKey(MR0, MR1, MR2, MR3);
            supersedes[MR5     ] = TechKey.BuildKey(MR0, MR1, MR2, MR3, MR4);

            //--------------------------------------------------
            //  ADD KEYS TO TECH-DEFINITIONS
            //--------------------------------------------------
            for (int i = 0; i < TechnologyCount; i++)
            {
                TechnologyDefinitions[i].SetTechKeys(supersedes[i], disables[i]);
            }
        }

        /// <summary>
        /// Builds a technology key based on the combination of zero or more of the specified technology paths and zero
        /// or more of the specified technology indexes.
        /// </summary>
        /// <param name="desiredPaths">Zero or more technology pathways for which to generate a technology key.</param>
        /// <param name="desiredTechIndexes">
        ///     Zero or more technology indexes for which to generate a technology key.
        /// </param>
        /// <returns>
        /// A technology key based on the combination of zero or more of the specified technology paths and zero or
        /// more of the specified technology indexes.
        /// </returns>
        static TechKey BuildTechKey(TechnologyPathways desiredPaths, params int[] desiredTechIndexes)
        {
            var filter = TechnologyDefinitions.Where(x => (desiredPaths & x.Pathway) == x.Pathway).ToList();
            var filteredTechs = filter.ConvertAll(x => x.Index).ToArray();

            return TechKey.BuildKey(filteredTechs) | TechKey.BuildKey(desiredTechIndexes);
        }

        /// <summary>
        /// Filters for indexes of technologies based on the specified flag.
        /// </summary>
        static int[] FilterTechnologies(TechnologyFlags flag)
        {
            var filter = TechnologyDefinitions.Where(item => item.IsFlagSet(flag)).ToList();
            return filter.ConvertAll(item => item.Index).ToArray();
        }

        /// <summary>
        /// Filters for names of technologies based on the specified flag.
        /// </summary>
        static string[] FilterTechnologyNames(TechnologyFlags flag)
        {
            var filter = TechnologyDefinitions.Where(item => item.IsFlagSet(flag)).ToList();
            return filter.ConvertAll(item => item.Name).ToArray();
        }

        #endregion

        #endregion
    }
}
