using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Resources;
using System.Text;
using System.Threading;
using MindWorks.Nimbus;
using Ivi.Driver;

[assembly: DriverCapabilities(Capabilities.AllExceptInterchangeCheck)]

[assembly: SCPICompliant(true)]
[assembly: BooleanCommand("1", "0")]

namespace Raytheon.GuidedElectronicsUnit
{
    public sealed class GuidedElectronicsUnit : Driver,
        IGuidedElectronicsUnit,
        IGuidedElectronicsUnitDiscrete,
        IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulator,
        IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA,
        IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelACS,
        IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelAPT,
        IGuidedElectronicsUnitGsKwSyncronousDataLinkControl,
        IGuidedElectronicsUnitInertialMeasurementUnitEmulator,
        IGuidedElectronicsUnitIntegratedDewarAssemblyInterfaceEmulator,
        IGuidedElectronicsUnitLowLevel,
        IGuidedElectronicsUnitLowLevelHSSub6020a,
        IGuidedElectronicsUnitLowLevelHSSub9100,
        IGuidedElectronicsUnitTestControl,
        IIviDriver,
        IIviDriverOperation,
        IIviDriverIdentity,
        IIviDriverUtility
    {
        #region Member fields

        //private bool enableLog = false;
        //private StreamWriter logFile = null;

        private int PollingInterval = 100; // In milliseconds
        private int MessageBufferSize = (int)10485760;

        private string _hsSub6020aResourceName = string.Empty;
        private HardwareSession6020a _hardwareSession6020a = null;

        private string _hsSub9100ResourceName = string.Empty;
        private HardwareSession9100 _hardwareSession9100 = null;

        private readonly bool _hardwareSessionReset = false;

        #endregion

        public GuidedElectronicsUnit(string resourceName, bool idQuery, bool reset)
            : this(resourceName, idQuery, reset, String.Empty)
        {
            _hardwareSessionReset = reset;
        }

        public GuidedElectronicsUnit(string resourceName, bool idQuery, bool reset, string options)
        {
            CallLoggingHelper.FunctionStart(GetType(), "ctor",
                nameof(resourceName), resourceName,
                nameof(idQuery), idQuery,
                nameof(reset), reset,
                nameof(options), options);
            try
            {
                _hardwareSessionReset = reset;

                // Do not remove this call to base.Initialize
                //
                base.Initialize(resourceName, idQuery, reset, options, LockType.AppDomain, String.Empty, 2000, 2000, 5000);

                //CallLoggingHelper.Message("Driver Information");
                //CallLoggingHelper.Message(string.Format("  {0,-30}: {1}", "Identifier", this.Identity.Identifier));
                //CallLoggingHelper.Message(string.Format("  {0,-30}: {1}", "Revision", this.Identity.Revision));
                //CallLoggingHelper.Message(string.Format("  {0,-30}: {1}", "Vendor", this.Identity.Vendor));
                //CallLoggingHelper.Message(string.Format("  {0,-30}: {1}", "InstrumentModel", this.Identity.InstrumentModel));
                //CallLoggingHelper.Message(string.Format("  {0,-30}: {1}", "InstrumentFirmwareRevision", this.Identity.InstrumentFirmwareRevision));
                //CallLoggingHelper.Message(string.Format("  {0,-30}: {1}", "InstrumentManufacturer", this.Identity.InstrumentManufacturer));
            }
            finally
            {
                CallLoggingHelper.FunctionEnd(GetType(), "ctor", null);
            }
        }

        public GuidedElectronicsUnit(string resourceName, bool idQuery, bool reset, LockType lockType, string accessKey, string options)
        {
            _hardwareSessionReset = reset;

            // Do not remove this call to base.Initialize
            //
            base.Initialize(resourceName, idQuery, reset, options, lockType, accessKey, 2000, 2000, 5000);
        }

        protected override void CleanupUnmanagedResources()
        {
            // Use this method to cleanup any driver-specific unmanaged resources
        }
        protected override void InitializeIO()
        {
            // Nothing to do, but the default implementation assumes SCPI instrument
            // This method doesn't get called if simulate is true
        }

        internal override void CloseIO()
        {
            // This method closes the I/O connection with the instrument.  For VISA-based drivers, this function
            // performs the viClose call on the I/O connection.  For custom I/O, this function performs whatever
            // cleanup tasks are necessary to free up whatever resources are held by the custom I/O implementation.
            //

            HardwareSessionFactory.EndHardwareSession(this, _hsSub6020aResourceName);
            _hardwareSession6020a = null;
            _hsSub6020aResourceName = string.Empty;

            // Wait for background thread to stop then dispose it
            if (_hardwareSession9100 != null)
            {
                _hardwareSession9100.messageChecker.CancelAsync();
                while (_hardwareSession9100.messageChecker.IsBusy)
                {
                    Thread.Sleep(1);
                }
                _hardwareSession9100.messageChecker.Dispose();
            }

            HardwareSessionFactory.EndHardwareSession(this, _hsSub9100ResourceName);
            _hardwareSession9100 = null;
            _hsSub9100ResourceName = string.Empty;

            //if (logFile != null)
            //{
            //    logFile.Flush();
            //    logFile.Close();
            //    logFile = null;
            //}
        }

        protected override void ClearIO()
        {
            // Nothing to do, but the default implementation assumes SCPI instrument
        }

        private HardwareSession6020a Get6020aSession()
        {
            if (_hardwareSession6020a == null)
                throw new InvalidOperationException("Hardware session to HSSub 6020A not initialized");

            return _hardwareSession6020a;
        }

        private HardwareSession9100 Get9100Session()
        {
            if (_hardwareSession9100 == null)
                throw new InvalidOperationException("Hardware session to HSSub 9100 not initialized");

            return _hardwareSession9100;
        }

        protected override void InitializeIdentification()
        {
            //SetupDebugLog();
            // If the resource string for the 6020a instrument was not specified as a Driver Setup option,
            // use the resource string specified in the constructor
            if (string.IsNullOrWhiteSpace(_hsSub6020aResourceName))
                _hsSub6020aResourceName = Session.ResourceDescriptor;


            if (!string.IsNullOrWhiteSpace(_hsSub6020aResourceName))
            {
                // Get the hardware session
                _hardwareSession6020a =
                    HardwareSessionFactory.NewHardwareSession<HardwareSession6020a>(this, _hsSub6020aResourceName,
                        Session.InitOptions.SimulationEnabled, _hardwareSessionReset);
            }

            if (!string.IsNullOrWhiteSpace(_hsSub9100ResourceName))
            {
                _hardwareSession9100 =
                    HardwareSessionFactory.NewHardwareSession<HardwareSession9100>(this, _hsSub9100ResourceName,
                        Session.InitOptions.SimulationEnabled, _hardwareSessionReset);
            }
        }

        internal override void InitNode()
        {
            base.InitNode();
            if (_hardwareSession9100 != null)
            {
                _hardwareSession9100.SetupBackgroundWorker(MessageBufferSize, PollingInterval);
            }
        }

        protected override void PollInstrumentErrors()
        {
            // Nothing to do, but the default implementation assumes SCPI instrument
        }

        //public void SendWarning(string message)
        //{
        //    Guid _guid = Guid.NewGuid();
        //    WarningEventArgs _args = new(_guid, message);
        //    SendWarningEvent(_args);
        //}

        //private void SetupDebugLog()
        //{
        //    if (enableLog)
        //    {
        //        var LogFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Raytheon", "DebugLogs", this.Identity.Identifier);
        //        if (!Directory.Exists(LogFilePath))
        //        {
        //            Directory.CreateDirectory(LogFilePath);
        //        }
        //        var timeStamp = string.Format("{0:yyyyMMdd_HHmmss}.txt", DateTime.Now);
        //        logFile = new StreamWriter(Path.Combine(LogFilePath, timeStamp));
        //    }
        //}

        #region IIviDriver

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        public IIviDriverOperation DriverOperation
        {
            get
            {
                return base.DefaultImplementation.Inherent.DriverOperation;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        public IIviDriverIdentity Identity
        {
            get
            {
                return base.DefaultImplementation.Inherent.Identity;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        public IIviDriverUtility Utility
        {
            get
            {
                return base.DefaultImplementation.Inherent.Utility;
            }
        }

        [DriverMethod(SuppressPollInstrumentErrors = true)]
        public void Close()
        {
            base.DefaultImplementation.Inherent.Close();
        }

        #endregion

        #region IIviDriverIdentity

        [DriverProperty(Lock = false, SuppressPollInstrumentErrors = true)]
        string IIviDriverIdentity.InstrumentManufacturer
        {
            get
            {
                return base.DefaultImplementation.Inherent.InstrumentManufacturer;
            }
        }

        [DriverProperty(Lock = false, SuppressPollInstrumentErrors = true)]
        string IIviDriverIdentity.InstrumentModel
        {
            get
            {
                return base.DefaultImplementation.Inherent.InstrumentModel;
            }
        }

        [DriverProperty(Lock = false, SuppressPollInstrumentErrors = true)]
        string IIviDriverIdentity.InstrumentFirmwareRevision
        {
            get
            {
                return base.DefaultImplementation.Inherent.InstrumentFirmwareRevision;
            }
        }

        [DriverProperty(Lock = false, SuppressPollInstrumentErrors = true)]
        string IIviDriverIdentity.Identifier
        {
            get
            {
                return base.DefaultImplementation.Inherent.Identifier;
            }
        }

        [DriverProperty(Lock = false, SuppressPollInstrumentErrors = true)]
        int IIviDriverIdentity.SpecificationMajorVersion
        {
            get
            {
                return base.DefaultImplementation.Inherent.SpecificationMajorVersion;
            }
        }

        [DriverProperty(Lock = false, SuppressPollInstrumentErrors = true)]
        int IIviDriverIdentity.SpecificationMinorVersion
        {
            get
            {
                return base.DefaultImplementation.Inherent.SpecificationMinorVersion;
            }
        }

        [DriverMethod(SuppressPollInstrumentErrors = true)]
        string[] IIviDriverIdentity.GetSupportedInstrumentModels()
        {
            return base.DefaultImplementation.Inherent.GetSupportedInstrumentModels();
        }

        [DriverMethod(SuppressPollInstrumentErrors = true)]
        string[] IIviDriverIdentity.GetGroupCapabilities()
        {
            return base.DefaultImplementation.Inherent.GetGroupCapabilities();
        }

        #endregion

        #region IIviDriverOperation

        [DriverEvent(SuppressPollInstrumentErrors = true)]
        event EventHandler<WarningEventArgs> IIviDriverOperation.Warning
        {
            add
            {
                base.Warning += value;
            }
            remove
            {
                base.Warning -= value;
            }
        }

        [DriverEvent(SuppressPollInstrumentErrors = true)]
        event EventHandler<CoercionEventArgs> IIviDriverOperation.Coercion
        {
            add
            {
                base.Coercion += value;
            }
            remove
            {
                base.Coercion -= value;
            }
        }

        [DriverEvent(SuppressPollInstrumentErrors = true)]
        event EventHandler<InterchangeCheckWarningEventArgs> IIviDriverOperation.InterchangeCheckWarning
        {
            add
            {
                base.InterchangeCheckWarning += value;
            }
            remove
            {
                base.InterchangeCheckWarning -= value;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        string IIviDriverOperation.LogicalName
        {
            get
            {
                return base.DefaultImplementation.Inherent.LogicalName;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        string IIviDriverOperation.IOResourceDescriptor
        {
            get
            {
                return base.DefaultImplementation.Inherent.IOResourceDescriptor;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        bool IIviDriverOperation.Cache
        {
            get
            {
                return base.DefaultImplementation.Inherent.Cache;
            }
            set
            {
                base.DefaultImplementation.Inherent.Cache = value;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        bool IIviDriverOperation.QueryInstrumentStatus
        {
            get
            {
                return base.DefaultImplementation.Inherent.QueryInstrumentStatus;
            }
            set
            {
                base.DefaultImplementation.Inherent.QueryInstrumentStatus = value;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        bool IIviDriverOperation.RangeCheck
        {
            get
            {
                return base.DefaultImplementation.Inherent.RangeCheck;
            }
            set
            {
                base.DefaultImplementation.Inherent.RangeCheck = value;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        bool IIviDriverOperation.Simulate
        {
            get
            {
                return base.DefaultImplementation.Inherent.Simulate;
            }
            set
            {
                base.DefaultImplementation.Inherent.Simulate = value;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        string IIviDriverOperation.DriverSetup
        {
            get
            {
                return base.DefaultImplementation.Inherent.DriverSetup;
            }
        }

        [DriverMethod(SuppressPollInstrumentErrors = true)]
        void IIviDriverOperation.ResetInterchangeCheck()
        {
            base.DefaultImplementation.Inherent.ResetInterchangeCheck();
        }

        [DriverMethod(SuppressPollInstrumentErrors = true)]
        void IIviDriverOperation.InvalidateAllAttributes()
        {
            base.DefaultImplementation.Inherent.InvalidateAllAttributes();
        }

        #endregion

        #region IIviDriverUtility

        [DriverMethod(SuppressPollInstrumentErrors = true)]
        ErrorQueryResult IIviDriverUtility.ErrorQuery()
        {
            return new ErrorQueryResult(0, "No Error");
        }

        [DriverMethod(SuppressPollInstrumentErrors = true)]
        SelfTestResult IIviDriverUtility.SelfTest()
        {
            return base.DefaultImplementation.Inherent.SelfTest();
        }

        [DriverMethod(SuppressPollInstrumentErrors = true)]
        void IIviDriverUtility.Disable()
        {
            base.DefaultImplementation.Inherent.Disable();
        }

        [DriverMethod(SuppressPollInstrumentErrors = true)]
        void IIviDriverUtility.ResetWithDefaults()
        {
            // Reset each instrument in use
            if (_hardwareSession6020a != null)
                _hardwareSession6020a.LowLevel.Reset();

            if (_hardwareSession9100 != null)
                _hardwareSession9100.LowLevel.Reset();
        }

        [DriverMethod(SuppressPollInstrumentErrors = true)]
        void IIviDriverUtility.Reset()
        {
            // Reset each instrument in use
            if (_hardwareSession6020a != null)
                _hardwareSession6020a.LowLevel.Reset();

            if (_hardwareSession9100 != null)
                _hardwareSession9100.LowLevel.Reset();
        }

        [DriverMethod(Lock = false, SuppressPollInstrumentErrors = true)]
        IIviDriverLock IIviDriverUtility.Lock()
        {
            return base.DefaultImplementation.Inherent.Lock();
        }

        [DriverMethod(Lock = false, SuppressPollInstrumentErrors = true)]
        IIviDriverLock IIviDriverUtility.Lock(PrecisionTimeSpan maxTime)
        {
            return base.DefaultImplementation.Inherent.Lock(maxTime);
        }

        #endregion

        #region IIviComponentIdentity

        [DriverProperty(Lock = false, SuppressPollInstrumentErrors = true)]
        string IIviComponentIdentity.Description
        {
            get
            {
                return base.DefaultImplementation.Inherent.Description;
            }
        }

        [DriverProperty(Lock = false, SuppressPollInstrumentErrors = true)]
        string IIviComponentIdentity.Revision
        {
            get
            {
                return base.DefaultImplementation.Inherent.Revision;
            }
        }

        [DriverProperty(Lock = false, SuppressPollInstrumentErrors = true)]
        string IIviComponentIdentity.Vendor
        {
            get
            {
                return base.DefaultImplementation.Inherent.Vendor;
            }
        }

        #endregion

        /// <summary>
        /// Override this method to process a custom DriverSetup option.  Custom DriverSetup options are driver-defined 
        /// name-value pairs that must be processed by this method.  Custom DriverSetup options do *not* include those 
        /// options common to all Nimbus drivers, such as the "Model" and "Trace" options.  This method is only called 
        /// when Nimbus cannot interpret a DriverSetup option.
        /// <para>
        /// Be default, this method throws an UnknownOptionException.  As such, it *must* be overridden in the main 
        /// driver class if the user specifies
        /// any custom DriverSetup options.
        /// </para>
        /// </summary>
        /// <param name="name">Name of the custom DriverSetup option.</param>
        /// <param name="value">Value of the custom DriverSetup option.</param>
        internal override void ProcessCustomDriverSetupOption(string name, string value)
        {
            switch (name.ToLower())
            {
                case "hssub6020a":
                    _hsSub6020aResourceName = value;
                    break;
                case "hssub9100":
                    _hsSub9100ResourceName = value;
                    break;
                case "pollinginterval":
                    PollingInterval = Convert.ToInt32(value);
                    break;
                case "messagebuffersize":
                    MessageBufferSize = Convert.ToInt32(value);
                    if (MessageBufferSize < 1024)
                    {
                        MessageBufferSize = 1024;
                    }
                    break;
                //case "debug":
                //    enableLog = (value.ToLower() == "on") ? true : false;
                //    break;
            }
        }

        #region IGuidedElectronicsUnit

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        public IGuidedElectronicsUnitDiscrete Discrete
        {
            get
            {
                return this;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        public IGuidedElectronicsUnitInertialMeasurementUnitEmulator InertialMeasurementUnitEmulator
        {
            get
            {
                return this;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        public IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulator EncryptorDecryptorAssemblyEmulator
        {
            get
            {
                return this;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        public IGuidedElectronicsUnitLowLevel LowLevel
        {
            get
            {
                return this;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        public IGuidedElectronicsUnitIntegratedDewarAssemblyInterfaceEmulator IntegratedDewarAssemblyInterfaceEmulator
        {
            get
            {
                return this;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        public IGuidedElectronicsUnitGsKwSyncronousDataLinkControl GsKwSyncronousDataLinkControl
        {
            get
            {
                return this;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        public IGuidedElectronicsUnitTestControl TestControl
        {
            get
            {
                return this;
            }
        }

        #endregion

        #region IGuidedElectronicsUnitLowLevel

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        IGuidedElectronicsUnitLowLevelHSSub6020a IGuidedElectronicsUnitLowLevel.HSSub6020a
        {
            get
            {
                return this;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        IGuidedElectronicsUnitLowLevelHSSub9100 IGuidedElectronicsUnitLowLevel.HSSub9100
        {
            get
            {
                return this;
            }
        }

        #endregion

        #region IGuidedElectronicsUnitLowLevelHSSub6020a

        [DriverMethod]
        FirmwareInformation IGuidedElectronicsUnitLowLevelHSSub6020a.GetFirmwareInfo() =>
            Get6020aSession().LowLevel.GetFirmwareInfo();

        [DriverMethod]
        TdfPllStatus IGuidedElectronicsUnitLowLevelHSSub6020a.GetPllStatus() =>
            Get6020aSession().LowLevel.GetPllStatus();

        [DriverMethod]
        uint IGuidedElectronicsUnitLowLevelHSSub6020a.ReadRegister(uint address) =>
            Get6020aSession().LowLevel.ReadRegister(address);

        [DriverMethod]
        void IGuidedElectronicsUnitLowLevelHSSub6020a.WriteRegister(uint address, uint data) =>
            Get6020aSession().LowLevel.WriteRegister(address, data);

        [DriverMethod]
        void IGuidedElectronicsUnitLowLevelHSSub6020a.Reset() =>
            Get6020aSession().LowLevel.Reset();

        [DriverMethod]
        void IGuidedElectronicsUnitLowLevelHSSub6020a.ReadModifyWrite(uint address, uint data, uint mask) =>
            Get6020aSession().LowLevel.ReadModifyWrite(address, data, mask);

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        int IGuidedElectronicsUnitLowLevelHSSub6020a.Chassis =>
            Get6020aSession().LowLevel.Chassis;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        string IGuidedElectronicsUnitLowLevelHSSub6020a.Descriptor =>
            Get6020aSession().LowLevel.Descriptor;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        string IGuidedElectronicsUnitLowLevelHSSub6020a.SerialNumber =>
            Get6020aSession().LowLevel.SerialNumber;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        int IGuidedElectronicsUnitLowLevelHSSub6020a.Slot =>
            Get6020aSession().LowLevel.Slot;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        double IGuidedElectronicsUnitLowLevelHSSub6020a.DieTemp =>
            Get6020aSession().LowLevel.DieTemp;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        double IGuidedElectronicsUnitLowLevelHSSub6020a.VccInt =>
            Get6020aSession().LowLevel.VccInt;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        double IGuidedElectronicsUnitLowLevelHSSub6020a.VccAux =>
            Get6020aSession().LowLevel.VccAux;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitLowLevelHSSub6020a.IsSimulated =>
            Get6020aSession().LowLevel.IsSimulated;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        Raytheon.GuidedElectronicsUnit.ControlState IGuidedElectronicsUnitLowLevelHSSub6020a.EnableIO
        {
            get => Get6020aSession().LowLevel.EnableIO;
            set => Get6020aSession().LowLevel.EnableIO = value;
        }

        [DriverMethod]
        void IGuidedElectronicsUnitLowLevelHSSub6020a.ResetEmStatus()
        {
            Get6020aSession().LowLevel.ResetEmStatus();
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        EmStatus IGuidedElectronicsUnitLowLevelHSSub6020a.EmStatus
        {
            get => Get6020aSession().LowLevel.EmStatus;
        }

        #endregion

        #region IGuidedElectronicsUnitLowLevelHSSub9100

        [DriverMethod]
        FirmwareInformation IGuidedElectronicsUnitLowLevelHSSub9100.GetFirmwareInfo() =>
            Get9100Session().LowLevel.GetFirmwareInfo();

        [DriverMethod]
        TdfPllStatus IGuidedElectronicsUnitLowLevelHSSub9100.GetPllStatus() =>
            Get9100Session().LowLevel.GetPllStatus();

        [DriverMethod]
        uint IGuidedElectronicsUnitLowLevelHSSub9100.ReadRegister(uint address) =>
            Get9100Session().LowLevel.ReadRegister(address);

        [DriverMethod]
        void IGuidedElectronicsUnitLowLevelHSSub9100.WriteRegister(uint address, uint data) =>
            Get9100Session().LowLevel.WriteRegister(address, data);

        [DriverMethod]
        void IGuidedElectronicsUnitLowLevelHSSub9100.Reset() =>
            Get9100Session().LowLevel.Reset();

        [DriverMethod]
        void IGuidedElectronicsUnitLowLevelHSSub9100.ReadModifyWrite(uint address, uint data, uint mask) =>
            Get9100Session().LowLevel.ReadModifyWrite(address, data, mask);

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        int IGuidedElectronicsUnitLowLevelHSSub9100.Chassis =>
            Get9100Session().LowLevel.Chassis;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        string IGuidedElectronicsUnitLowLevelHSSub9100.Descriptor =>
            Get9100Session().LowLevel.Descriptor;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        string IGuidedElectronicsUnitLowLevelHSSub9100.SerialNumber =>
            Get9100Session().LowLevel.SerialNumber;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        int IGuidedElectronicsUnitLowLevelHSSub9100.Slot =>
            Get9100Session().LowLevel.Slot;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        double IGuidedElectronicsUnitLowLevelHSSub9100.DieTemp =>
            Get9100Session().LowLevel.DieTemp;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        double IGuidedElectronicsUnitLowLevelHSSub9100.VccInt =>
            Get9100Session().LowLevel.VccInt;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        double IGuidedElectronicsUnitLowLevelHSSub9100.VccAux =>
            Get9100Session().LowLevel.VccAux;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitLowLevelHSSub9100.IsSimulated =>
            Get9100Session().LowLevel.IsSimulated;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        Raytheon.GuidedElectronicsUnit.ControlState IGuidedElectronicsUnitLowLevelHSSub9100.EnableIO
        {
            get => Get9100Session().LowLevel.EnableIO;
            set => Get9100Session().LowLevel.EnableIO = value;
        }

        [DriverMethod]
        AuroraStatus IGuidedElectronicsUnitLowLevelHSSub9100.GetAuroraStatus() =>
            Get9100Session().LowLevel.GetAuroraStatus();

        #endregion

        #region IGuidedElectronicsUnitInertialMeasurementUnitEmulator

        [DriverMethod]
        SdlcStatus IGuidedElectronicsUnitInertialMeasurementUnitEmulator.FetchStatus() =>
            Get9100Session().ImuEmulator.FetchStatus();

        [DriverMethod]
        void IGuidedElectronicsUnitInertialMeasurementUnitEmulator.SetDataWord(ImuMessageWord word, uint data) =>
            Get9100Session().ImuEmulator.SetDataWord(word, data);

        [DriverMethod]
        ImuMessage IGuidedElectronicsUnitInertialMeasurementUnitEmulator.FetchMessageData() =>
            Get9100Session().ImuEmulator.FetchMessageData();

        [DriverMethod]
        void IGuidedElectronicsUnitInertialMeasurementUnitEmulator.Configure(ImuConfigure control, Raytheon.GuidedElectronicsUnit.ControlState state) =>
            Get9100Session().ImuEmulator.Configure(control, state);

        [DriverMethod]
        ImuConfig IGuidedElectronicsUnitInertialMeasurementUnitEmulator.FetchConfiguration() =>
            Get9100Session().ImuEmulator.FetchConfiguration();

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        double IGuidedElectronicsUnitInertialMeasurementUnitEmulator.EODSampleWidth
        {
            get => Get9100Session().ImuEmulator.EODSampleWidth;
            set => Get9100Session().ImuEmulator.EODSampleWidth = value;
        }

        [DriverMethod]
        ImuDiscreteInput IGuidedElectronicsUnitInertialMeasurementUnitEmulator.FetchDiscreteInput() =>
            Get9100Session().ImuEmulator.FetchDiscreteInput();

        [DriverMethod]
        void IGuidedElectronicsUnitInertialMeasurementUnitEmulator.SdlcControl(SdlcControlBits control, ControlState state) =>
            Get9100Session().ImuEmulator.SdlcControl(control, state);

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        SdlcFifoWrCount IGuidedElectronicsUnitInertialMeasurementUnitEmulator.FifoWrCount
        {
            get => Get9100Session().ImuEmulator.FifoWrCount;
        }

        [DriverMethod]
        RxSdlcMessage IGuidedElectronicsUnitInertialMeasurementUnitEmulator.ReadMessage() =>
            Get9100Session().ImuEmulator.ReadMessage();

        [DriverMethod]
        RxSdlcMessage[] IGuidedElectronicsUnitInertialMeasurementUnitEmulator.ReadAllMessages() =>
            Get9100Session().ImuEmulator.ReadAllMessages();

        [DriverMethod]
        void IGuidedElectronicsUnitInertialMeasurementUnitEmulator.SendMessage(uint[] data) =>
            Get9100Session().ImuEmulator.SendMessage(data);

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        Raytheon.GuidedElectronicsUnit.ControlState IGuidedElectronicsUnitInertialMeasurementUnitEmulator.FrameEnable
        {
            get => Get9100Session().ImuEmulator.FrameEnable;
            set => Get9100Session().ImuEmulator.FrameEnable = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        [RangeCheckMinMax(1E-08, 2.68435455, MinInclusive = true, MaxInclusive = true)]
        double IGuidedElectronicsUnitInertialMeasurementUnitEmulator.FramePeriod
        {
            get => Get9100Session().ImuEmulator.FramePeriod;
            set => Get9100Session().ImuEmulator.FramePeriod = value;
        }

        #endregion

        #region IGuidedElectronicsUnitIntegratedDewarAssemblyInterfaceEmulator

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        Raytheon.GuidedElectronicsUnit.ControlState IGuidedElectronicsUnitIntegratedDewarAssemblyInterfaceEmulator.Control
        {
            get => Get6020aSession().IdaEmulator.Control;
            set => Get6020aSession().IdaEmulator.Control = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        IdaStatus IGuidedElectronicsUnitIntegratedDewarAssemblyInterfaceEmulator.Status =>
            Get6020aSession().IdaEmulator.Status;

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        uint IGuidedElectronicsUnitIntegratedDewarAssemblyInterfaceEmulator.Version =>
            Get6020aSession().IdaEmulator.Version;

        #endregion

        #region IGuidedElectronicsUnitDiscrete

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        Raytheon.GuidedElectronicsUnit.SignalState IGuidedElectronicsUnitDiscrete.NcDacsKwOrdEn
        {
            get
            {
                return Get9100Session().Discrete.NcDacsKwOrdEn;
            }
        }

        #endregion

        #region IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulator

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulator.ChannelA
        {
            get
            {
                return this;
            }
        }

        #endregion

        #region IGuidedElectronicsUnitGsKwSyncronousDataLinkControl

        [DriverMethod]
        void IGuidedElectronicsUnitGsKwSyncronousDataLinkControl.SdlcControl(SdlcControlBits control, ControlState state)
        {
            Get9100Session().GsKwSDLC.SdlcControl(control, state);
        }

        [DriverMethod]
        SdlcStatus IGuidedElectronicsUnitGsKwSyncronousDataLinkControl.FetchStatus()
        {
            return Get9100Session().GsKwSDLC.FetchStatus();
        }

        [DriverMethod]
        void IGuidedElectronicsUnitGsKwSyncronousDataLinkControl.SendMessage(uint[] data) =>
            Get9100Session().GsKwSDLC.SendMessage(data);

        [DriverEvent]
        event EventHandler<SdlcEventArgs> IGuidedElectronicsUnitGsKwSyncronousDataLinkControl.AutoForwardBufferCapacityWarning
        {
            add => Get9100Session().GsKwSDLC.AutoForwardBufferCapacityWarning += value;
            remove => Get9100Session().GsKwSDLC.AutoForwardBufferCapacityWarning -= value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        SdlcFifoWrCount IGuidedElectronicsUnitGsKwSyncronousDataLinkControl.FifoWrCount
        {
            get => Get9100Session().GsKwSDLC.FifoWrCount;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitGsKwSyncronousDataLinkControl.Sync
        {
            get => Get9100Session().GsKwSDLC.Sync;
            set => Get9100Session().GsKwSDLC.Sync = value;
        }

        [DriverMethod]
        byte[] IGuidedElectronicsUnitGsKwSyncronousDataLinkControl.FetchMessageData() =>
            Get9100Session().GsKwSDLC.FetchMessageData();

        [DriverMethod]
        RxSdlcMessage IGuidedElectronicsUnitGsKwSyncronousDataLinkControl.ReadMessage() =>
            Get9100Session().GsKwSDLC.ReadMessage();

        [DriverMethod]
        RxSdlcMessage[] IGuidedElectronicsUnitGsKwSyncronousDataLinkControl.ReadAllMessages() =>
            Get9100Session().GsKwSDLC.ReadAllMessages();

        [DriverEvent]
        event EventHandler<SdlcEventArgs> IGuidedElectronicsUnitGsKwSyncronousDataLinkControl.AutoForwardProcessExited
        {
            add => Get9100Session().GsKwSDLC.AutoForwardProcessExited += value;
            remove => Get9100Session().GsKwSDLC.AutoForwardProcessExited -= value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        RxSdlcAutoForwardBuffer IGuidedElectronicsUnitGsKwSyncronousDataLinkControl.SdlcAutoForwardBuffer =>
            Get9100Session().GsKwSDLC.SdlcAutoForwardBuffer;

        #endregion

        #region IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelAPT IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.PT
        {
            get
            {
                return this;
            }
        }

        [DriverProperty(SuppressPollInstrumentErrors = true)]
        IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelACS IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.CS
        {
            get
            {
                return this;
            }
        }

        [DriverMethod]
        Scoreboard IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.FetchScoreboard() =>
            Get9100Session().EdaEmulator.ChannelA.FetchScoreboard();

        [DriverMethod]
        KwdlStatus IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.FetchKwdlStatus() =>
            Get9100Session().EdaEmulator.ChannelA.FetchKwdlStatus();

        [DriverMethod]
        CvcwData IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.FetchCVCWData() =>
            Get9100Session().EdaEmulator.ChannelA.FetchCVCWData();

        [DriverMethod]
        byte[] IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.FetchCVData() =>
            Get9100Session().EdaEmulator.ChannelA.FetchCVData();

        [DriverMethod]
        EdaStatus IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.FetchEdaStatus() =>
            Get9100Session().EdaEmulator.ChannelA.FetchEdaStatus();

        [DriverMethod]
        void IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.Configure(EdaConfig configuration) =>
            Get9100Session().EdaEmulator.ChannelA.Configure(configuration);

        [DriverMethod]
        EdaConfig IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.FetchConfiguration() =>
            Get9100Session().EdaEmulator.ChannelA.FetchConfiguration();

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.EdaPbitValid
        {
            get => Get9100Session().EdaEmulator.ChannelA.EdaPbitValid;
            set => Get9100Session().EdaEmulator.ChannelA.EdaPbitValid = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.EdaPbitPass
        {
            get => Get9100Session().EdaEmulator.ChannelA.EdaPbitPass;
            set => Get9100Session().EdaEmulator.ChannelA.EdaPbitPass = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.EdaCVReadyValid
        {
            get => Get9100Session().EdaEmulator.ChannelA.EdaCVReadyValid;
            set => Get9100Session().EdaEmulator.ChannelA.EdaCVReadyValid = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.EdaCVReady
        {
            get => Get9100Session().EdaEmulator.ChannelA.EdaCVReady;
            set => Get9100Session().EdaEmulator.ChannelA.EdaCVReady = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.EdaCVClearPassFailValid
        {
            get => Get9100Session().EdaEmulator.ChannelA.EdaCVClearPassFailValid;
            set => Get9100Session().EdaEmulator.ChannelA.EdaCVClearPassFailValid = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.EdaCVClearPassFail
        {
            get => Get9100Session().EdaEmulator.ChannelA.EdaCVClearPassFail;
            set => Get9100Session().EdaEmulator.ChannelA.EdaCVClearPassFail = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        short IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.EdaNumCVClear
        {
            get => Get9100Session().EdaEmulator.ChannelA.EdaNumCVClear;
            set => Get9100Session().EdaEmulator.ChannelA.EdaNumCVClear = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        short IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.KwdlRFTemp
        {
            get => Get9100Session().EdaEmulator.ChannelA.KwdlRFTemp;
            set => Get9100Session().EdaEmulator.ChannelA.KwdlRFTemp = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.KwdlMbitPass
        {
            get => Get9100Session().EdaEmulator.ChannelA.KwdlMbitPass;
            set => Get9100Session().EdaEmulator.ChannelA.KwdlMbitPass = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.KwdlMbitComplete
        {
            get => Get9100Session().EdaEmulator.ChannelA.KwdlMbitComplete;
            set => Get9100Session().EdaEmulator.ChannelA.KwdlMbitComplete = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.KwdlPbitPass
        {
            get => Get9100Session().EdaEmulator.ChannelA.KwdlPbitPass;
            set => Get9100Session().EdaEmulator.ChannelA.KwdlPbitPass = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        Raytheon.GuidedElectronicsUnit.KwdlState IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.KwdlState
        {
            get => Get9100Session().EdaEmulator.ChannelA.KwdlState;
            set => Get9100Session().EdaEmulator.ChannelA.KwdlState = value;
        }

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        bool IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelA.KwdlLinkUp
        {
            get => Get9100Session().EdaEmulator.ChannelA.KwdlLinkUp;
            set => Get9100Session().EdaEmulator.ChannelA.KwdlLinkUp = value;
        }

        #endregion

        #region IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelACS

        [DriverMethod]
        SdlcStatus IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelACS.FetchSdlcStatus() =>
            Get9100Session().EdaEmulator.ChannelA.CS.FetchSdlcStatus();

        [DriverMethod]
        void IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelACS.SdlcControl(SdlcControlBits control, ControlState state) =>
            Get9100Session().EdaEmulator.ChannelA.CS.SdlcControl(control, state);

        [DriverMethod]
        RxSdlcMessage[] IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelACS.ReadAllMessages() =>
            Get9100Session().EdaEmulator.ChannelA.CS.ReadAllMessages();

        [DriverMethod]
        RxSdlcMessage IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelACS.ReadMessage() =>
            Get9100Session().EdaEmulator.ChannelA.CS.ReadMessage();

        [DriverMethod]
        void IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelACS.SendMessage(uint[] data) =>
            Get9100Session().EdaEmulator.ChannelA.CS.SendMessage(data);

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        SdlcFifoWrCount IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelACS.FifoWrCount
        {
            get => Get9100Session().EdaEmulator.ChannelA.CS.FifoWrCount;
        }

        #endregion

        #region IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelAPT

        [DriverMethod]
        void IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelAPT.SdlcControl(SdlcControlBits control, ControlState state) =>
            Get9100Session().EdaEmulator.ChannelA.PT.SdlcControl(control, state);

        [DriverMethod]
        SdlcStatus IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelAPT.FetchSdlcStatus() =>
            Get9100Session().EdaEmulator.ChannelA.PT.FetchSdlcStatus();

        [DriverMethod]
        RxSdlcMessage[] IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelAPT.ReadAllMessages() =>
            Get9100Session().EdaEmulator.ChannelA.PT.ReadAllMessages();

        [DriverMethod]
        RxSdlcMessage IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelAPT.ReadMessage() =>
            Get9100Session().EdaEmulator.ChannelA.PT.ReadMessage();

        [DriverMethod]
        void IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelAPT.SendMessage(uint[] data) =>
            Get9100Session().EdaEmulator.ChannelA.PT.SendMessage(data);

        [DriverProperty]
        [Simulation(SimulationMode.Manual)]
        SdlcFifoWrCount IGuidedElectronicsUnitEncryptorDecryptorAssemblyEmulatorChannelAPT.FifoWrCount
        {
            get => Get9100Session().EdaEmulator.ChannelA.CS.FifoWrCount;
        }

        #endregion

        #region IGuidedElectronicsUnitTestControl

        [DriverMethod]
        void IGuidedElectronicsUnitTestControl.WaitForMsg(ushort count) =>
            Get9100Session().Test.WaitForMsg(count);

        #endregion
    }
}
