/// <summary>
 /// See interface docs.
 /// </summary>
 /// <param name="aircraftInformation"></param>
 public void MoveAircraft(WriteAircraftInformation aircraftInformation)
 {
     if(Connected && _SimConnect.IsInstalled) {
         _SimConnect.SetDataOnSimObject(DefinitionId.WriteAircraftInformation, (uint)SIMCONNECT_SIMOBJECT_TYPE.USER, (int)SIMCONNECT_DATA_SET_FLAG.DEFAULT, aircraftInformation);
     }
 }
        /// <summary>
        /// Repositions the FSX aircraft to match the location, speed and attitude of a real aircraft.
        /// </summary>
        private void MoveAircraft()
        {
            var selectedAircraft = _View.SelectedRealAircraft;

            if(_View.RidingAircraft && selectedAircraft != null) {
                long trash1, trash2;
                var aircraft = BaseStationAircraftList.TakeSnapshot(out trash1, out trash2).Where(a => a.UniqueId == selectedAircraft.UniqueId).FirstOrDefault();
                if(aircraft != null) {
                    var speedLimit = (float)_MaximumAirspeed - 30f;

                    var writeAircraftInformation = new WriteAircraftInformation();
                    writeAircraftInformation.AirspeedIndicated = aircraft.GroundSpeed > speedLimit ? speedLimit : aircraft.GroundSpeed.GetValueOrDefault();
                    aircraft.GroundSpeed.GetValueOrDefault();
                    writeAircraftInformation.Altitude = aircraft.Altitude.GetValueOrDefault();
                    writeAircraftInformation.Operator = aircraft.Operator;
                    writeAircraftInformation.Registration = aircraft.Registration;
                    //writeAircraftInformation.Type = aircraft.Type;
                    //writeAircraftInformation.Model = aircraft.Model;
                    writeAircraftInformation.Latitude = aircraft.Latitude.GetValueOrDefault();
                    writeAircraftInformation.Longitude = aircraft.Longitude.GetValueOrDefault();
                    writeAircraftInformation.TrueHeading = aircraft.Track.GetValueOrDefault();
                    writeAircraftInformation.VerticalSpeed = aircraft.VerticalRate.GetValueOrDefault();
                    writeAircraftInformation.Bank = ApproximateBank(_MovedAircraft, aircraft);

                    _MovedAircraft = aircraft;

                    _FlightSimulatorX.MoveAircraft(writeAircraftInformation);
                }
            }
        }
        public void FlightSimulatorXPresenter_RidingAircraft_Airspeed_Is_Kept_Below_FSX_Aircraft_Maximum_Airspeed()
        {
            // The FSX aircraft need not be the same type etc. as the real-life one. If we exceed the FSX airspeed then it will simulate a crash in FSX, so we
            // need to pick up the maximum airspeed when reading aircraft information from FSX and use that to moderate the airspeed before writing it back to
            // FSX.

            _Presenter.Initialise(_View.Object);

            _FlightSimulatorX.Setup(f => f.Connected).Returns(true);
            _FlightSimulatorX.Raise(f => f.ConnectionStatusChanged += null, EventArgs.Empty);

            var aircraft = new Mock<IAircraft>() { DefaultValue = DefaultValue.Mock }.SetupAllProperties();
            aircraft.Object.UniqueId = 17;
            aircraft.Object.GroundSpeed = 320;
            _RealAircraftList.Add(aircraft.Object);

            _SelectedAircraft.UniqueId = 17;

            WriteAircraftInformation aircraftInformation = new WriteAircraftInformation();
            _FlightSimulatorX.Setup(f => f.MoveAircraft(It.IsAny<WriteAircraftInformation>())).Callback((WriteAircraftInformation writeAircraftInformation) => {
                aircraftInformation = writeAircraftInformation;
            });

            _View.Raise(v => v.RideAircraftClicked += null, EventArgs.Empty);
            _FlightSimulatorX.Raise(f => f.AircraftInformationReceived += null, new EventArgs<ReadAircraftInformation>(new ReadAircraftInformation() { MaxAirspeedIndicated = 200 }));

            _View.Raise(v => v.RefreshFlightSimulatorXInformation += null, EventArgs.Empty);

            Assert.AreEqual(170, aircraftInformation.AirspeedIndicated);
        }
        public void FlightSimulatorXPresenter_RidingAircraft_Approximates_Bank_Angle_From_Track()
        {
            var worksheet = new ExcelWorksheetData(TestContext);

            _Presenter.Initialise(_View.Object);

            WriteAircraftInformation aircraftInformation = new WriteAircraftInformation();
            _FlightSimulatorX.Setup(f => f.MoveAircraft(It.IsAny<WriteAircraftInformation>())).Callback((WriteAircraftInformation writeAircraftInformation) => {
                aircraftInformation = writeAircraftInformation;
            });

            _FlightSimulatorX.Setup(f => f.Connected).Returns(true);
            _FlightSimulatorX.Raise(f => f.ConnectionStatusChanged += null, EventArgs.Empty);

            _SelectedAircraft.UniqueId = 1;

            _View.Raise(v => v.RideAircraftClicked += null, EventArgs.Empty);

            for(var i = 1;i <= 3;++i) {
                string uniqueIdColumn = String.Format("UniqueId{0}", i);
                string updateTimeColumn = String.Format("UpdateTime{0}", i);
                string trackColumn = String.Format("Track{0}", i);
                string bankColumn = String.Format("Bank{0}", i);

                if(worksheet.String(uniqueIdColumn) == null) break;

                var aircraft = new Mock<IAircraft>() { DefaultValue = DefaultValue.Mock }.SetupAllProperties().Object;
                if(_RealAircraftList.Count == 0) _RealAircraftList.Add(aircraft);
                else                             _RealAircraftList[0] = aircraft;

                _SelectedAircraft.UniqueId = aircraft.UniqueId = worksheet.Int(uniqueIdColumn);
                aircraft.LastUpdate = worksheet.DateTime(updateTimeColumn);
                aircraft.Track = worksheet.NFloat(trackColumn);
                _View.Raise(v => v.RefreshFlightSimulatorXInformation += null, EventArgs.Empty);
                Assert.AreEqual(worksheet.Double(bankColumn), aircraftInformation.Bank, i.ToString());
            }
        }
        public void FlightSimulatorXPresenter_RidingAircraft_Sends_Real_World_Aircraft_Information_To_FSX_On_View_Timer_Tick()
        {
            var worksheet = new ExcelWorksheetData(TestContext);

            _Presenter.Initialise(_View.Object);

            _Provider.Setup(p => p.UtcNow).Returns(worksheet.DateTime("UtcNow"));

            _SelectedAircraft.UniqueId = 92;

            var aircraft = new Mock<IAircraft>() { DefaultValue = DefaultValue.Mock }.SetupAllProperties();
            _RealAircraftList.Add(aircraft.Object);
            aircraft.Object.UniqueId = 92;
            aircraft.Object.Latitude = worksheet.NFloat("Latitude");
            aircraft.Object.Longitude = worksheet.NFloat("Longitude");
            aircraft.Object.PositionTime = worksheet.NDateTime("PositionTime");
            aircraft.Object.GroundSpeed = worksheet.NFloat("GroundSpeed");
            aircraft.Object.Track = worksheet.NFloat("Track");
            aircraft.Object.Type = worksheet.String("Type");
            aircraft.Object.Model = worksheet.String("Model");
            aircraft.Object.Operator = worksheet.String("Operator");
            aircraft.Object.Registration = worksheet.String("Registration");
            aircraft.Object.Squawk = worksheet.NInt("Squawk");
            aircraft.Object.Altitude = worksheet.NInt("Altitude");
            aircraft.Object.VerticalRate = worksheet.NInt("VerticalRate");

            WriteAircraftInformation aircraftInformation = new WriteAircraftInformation();
            _FlightSimulatorX.Setup(f => f.MoveAircraft(It.IsAny<WriteAircraftInformation>())).Callback((WriteAircraftInformation writeAircraftInformation) => {
                aircraftInformation = writeAircraftInformation;
            });

            _FlightSimulatorX.Setup(f => f.Connected).Returns(true);
            _FlightSimulatorX.Raise(f => f.ConnectionStatusChanged += null, EventArgs.Empty);

            _View.Raise(v => v.RideAircraftClicked += null, EventArgs.Empty);
            _View.Raise(v => v.RefreshFlightSimulatorXInformation += null, EventArgs.Empty);

            _FlightSimulatorX.Verify(f => f.MoveAircraft(It.IsAny<WriteAircraftInformation>()), Times.Once());

            Assert.AreEqual(worksheet.Double("FSXAirspeedIndicated"), aircraftInformation.AirspeedIndicated);
            Assert.AreEqual(worksheet.Double("FSXAltitude"), aircraftInformation.Altitude);
            Assert.AreEqual(worksheet.Double("FSXLatitude"), aircraftInformation.Latitude, 0.001);
            Assert.AreEqual(worksheet.Double("FSXLongitude"), aircraftInformation.Longitude, 0.001);
            Assert.AreEqual(worksheet.String("FSXOperator"), aircraftInformation.Operator);
            Assert.AreEqual(worksheet.String("FSXRegistration"), aircraftInformation.Registration);
            Assert.AreEqual(worksheet.Double("FSXTrueHeading"), aircraftInformation.TrueHeading, 0.001);
            Assert.AreEqual(worksheet.Double("FSXVerticalSpeed"), aircraftInformation.VerticalSpeed);
        }
        public void TestInitialise()
        {
            _OriginalClassFactory = Factory.Singleton.CreateChildFactory();

            _SimConnect = TestUtilities.CreateMockImplementation<ISimConnectWrapper>();
            _SimConnect.Setup(m => m.IsInstalled).Returns(true);

            _Fsx = Factory.Singleton.Resolve<IFlightSimulatorX>();

            _ClientEventIdMap = new Dictionary<string,Enum>();
            _SimConnect.Setup(m => m.MapClientEventToSimEvent(It.IsAny<Enum>(), It.IsAny<string>())).Callback((Enum id, string name) => { _ClientEventIdMap.Add(name, id); });

            _SystemEventIdMap = new Dictionary<string,Enum>();
            _SimConnect.Setup(m => m.SubscribeToSystemEvent(It.IsAny<Enum>(), It.IsAny<string>())).Callback((Enum id, string name) => { _SystemEventIdMap.Add(name, id); });

            _NotificationGroupMap = new Dictionary<Enum,Enum>();
            _SimConnect.Setup(m => m.AddClientEventToNotificationGroup(It.IsAny<Enum>(), It.IsAny<Enum>(), false)).Callback((Enum groupId, Enum eventId, bool maskable) => { _NotificationGroupMap.Add(eventId, groupId); });

            _ReadAircraftInformationDefinitionId = default(Enum);
            _SimConnect.Setup(m => m.RegisterDataDefineStruct<ReadAircraftInformation>(It.IsAny<Enum>())).Callback((Enum definitionId) => { _ReadAircraftInformationDefinitionId = definitionId; });

            _AircraftInformationRequestId = default(Enum);
            _SimConnect.Setup(m => m.RequestDataOnSimObjectType(It.IsAny<Enum>(), It.IsAny<Enum>(), It.IsAny<uint>(), It.IsAny<int>())).Callback((Enum requestId, Enum definitionId, uint radius, int objectType) => {
                if(definitionId == _ReadAircraftInformationDefinitionId) _AircraftInformationRequestId = requestId;
            });

            _WriteAircraftInformationDefinitionId = default(Enum);
            _SimConnect.Setup(m => m.RegisterDataDefineStruct<WriteAircraftInformation>(It.IsAny<Enum>())).Callback((Enum definitionId) => { _WriteAircraftInformationDefinitionId = definitionId; });

            _ConnectionStatusChangedEvent = new EventRecorder<EventArgs>();
            _FreezeStatusChangedEvent = new EventRecorder<EventArgs>();
            _SlewStatusChangedEvent = new EventRecorder<EventArgs>();
            _FlightSimulatorXExceptionRaisedEvent = new EventRecorder<EventArgs<FlightSimulatorXException>>();
            _AircraftInformationReceivedEvent = new EventRecorder<EventArgs<ReadAircraftInformation>>();
            _SlewToggledEvent = new EventRecorder<EventArgs>();

            _ReadAircraftInformation = new ReadAircraftInformation();
            _WriteAircraftInformation = new WriteAircraftInformation();
            _Message = new Message();
        }