//[TestMethod]
        //public async Task AnalyzeMoveShouldCountPeopleNumberInHouse()
        //{
        //    var (motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithConfusionResolutionTime(TimeSpan.FromMilliseconds(5000))
        //                                                                                   .WithMotion
        //    (
        //      OnNext(Time.Tics(500), new MotionEnvelope(Detectors.toiletDetector)),
        //      OnNext(Time.Tics(1500), new MotionEnvelope(Detectors.hallwayDetectorToilet)),
        //      OnNext(Time.Tics(2000), new MotionEnvelope(Detectors.kitchenDetector)),
        //      OnNext(Time.Tics(2500), new MotionEnvelope(Detectors.livingRoomDetector)),
        //      OnNext(Time.Tics(3000), new MotionEnvelope(Detectors.hallwayDetectorLivingRoom)),
        //      OnNext(Time.Tics(3500), new MotionEnvelope(Detectors.hallwayDetectorToilet)),
        //      OnNext(Time.Tics(4000), new MotionEnvelope(Detectors.kitchenDetector))
        //    ).Build();

        //    scheduler.AdvanceTo(TimeSpan.FromMilliseconds(15000));

        //    var status = await _context.Query<MotionStatus>(MotionServiceStatusQuery.Create());
        //    Assert.AreEqual(2, status.NumberOfPersonsInHouse);
        //}

        //[TestMethod]
        //public async Task Move_SplitFromOneRoom_ShouldCountPeople()
        //{
        //    new LightAutomationEnviromentBuilder(_context).WithServiceConfig(DefaultServiceConfig().Build()).WithMotions(new Dictionary<int, string>
        //    {
        //        { 1000, Detectors.livingRoomDetector },
        //        { 2000, Detectors.hallwayDetectorLivingRoom },
        //        { 2900, Detectors.bathroomDetector },
        //        { 3000, Detectors.hallwayDetectorToilet },
        //        { 4000, Detectors.kitchenDetector },
        //    }).Start();

        //    AdvanceJustAfter(TimeSpan.FromSeconds(4));

        //    var status = await Query<MotionStatus>(MotionServiceStatusQuery.Create());
        //    var numKitchen = await Query<int>(NumberOfPeopleQuery.Create(Detectors.kitchenDetector));
        //    var numBathroom = await Query<int>(NumberOfPeopleQuery.Create(Detectors.bathroomDetector));

        //    numKitchen.Should().Be(1);
        //    numBathroom.Should().Be(1);

        //    IsTurnedOn(Detectors.kitchenDetector).Should().BeTrue();
        //    IsTurnedOn(Detectors.bathroomDetector).Should().BeTrue();
        //    IsTurnedOn(Detectors.hallwayDetectorLivingRoom).Should().BeFalse();
        //    //  Assert.AreEqual(2, status.NumberOfPersonsInHouse);
        //    //Assert.AreEqual(false, lampDictionary[Detectors.livingRoomDetector].IsTurnedOn);
        //    AdvanceJustAfter(TimeSpan.FromSeconds(5));
        //    IsTurnedOn(Detectors.hallwayDetectorToilet).Should().BeFalse();
        //}



        /// <summary>
        /// Get predefinied rooms configuration
        /// </summary>
        /// <returns></returns>
        private LightAutomationServiceBuilder Default()
        {
            var builder = new LightAutomationServiceBuilder();

            builder.WithRoom(new RoomBuilder(Rooms.Hallway).WithDetector(Detectors.hallwayDetectorToilet, new List <string> {
                Detectors.hallwayDetectorLivingRoom, Detectors.kitchenDetector, Detectors.staircaseDetector, Detectors.toiletDetector
            })
                             .WithDetector(Detectors.hallwayDetectorLivingRoom, new List <string> {
                Detectors.livingRoomDetector, Detectors.bathroomDetector, Detectors.hallwayDetectorToilet
            }));
            builder.WithRoom(new RoomBuilder(Rooms.Badroom).WithDetector(Detectors.badroomDetector, new List <string> {
                Detectors.hallwayDetectorLivingRoom
            }));
            builder.WithRoom(new RoomBuilder(Rooms.Balcony).WithDetector(Detectors.balconyDetector, new List <string> {
                Detectors.hallwayDetectorLivingRoom
            }));
            builder.WithRoom(new RoomBuilder(Rooms.Bathroom).WithDetector(Detectors.bathroomDetector, new List <string> {
                Detectors.hallwayDetectorLivingRoom
            }));
            builder.WithRoom(new RoomBuilder(Rooms.Kitchen).WithDetector(Detectors.kitchenDetector, new List <string> {
                Detectors.hallwayDetectorToilet
            }));
            builder.WithRoom(new RoomBuilder(Rooms.Livingroom).WithDetector(Detectors.livingRoomDetector, new List <string> {
                Detectors.livingRoomDetector
            }));
            builder.WithRoom(new RoomBuilder(Rooms.Staircase).WithDetector(Detectors.staircaseDetector, new List <string> {
                Detectors.hallwayDetectorToilet
            }));
            builder.WithRoom(new RoomBuilder(Rooms.Toilet).WithDetector(Detectors.toiletDetector, new List <string> {
                Detectors.hallwayDetectorToilet
            }).WithProperty(MotionProperties.MaxPersonCapacity, "1"));

            return(builder);
        }
        public void WhenNoConfusionMoveThroughManyRoomsShouldTurnOfLightImmediately()
        {
            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithMotion
                                                           (
                OnNext(Time.Tics(1000), new MotionEnvelope(Detectors.livingRoomDetector)),
                OnNext(Time.Tics(2000), new MotionEnvelope(Detectors.hallwayDetectorLivingRoom)),
                OnNext(Time.Tics(3000), new MotionEnvelope(Detectors.hallwayDetectorToilet)),
                OnNext(Time.Tics(4000), new MotionEnvelope(Detectors.kitchenDetector))
                                                           ).Build();

            scheduler.AdvanceJustAfter(TimeSpan.FromSeconds(2));

            Assert.AreEqual(true, lampDictionary[Detectors.livingRoomDetector].IsTurnedOn);
            Assert.AreEqual(true, lampDictionary[Detectors.hallwayDetectorLivingRoom].IsTurnedOn);
            //  scheduler.AdvanceJustAfter(TimeSpan.FromSeconds(3));
            //   Assert.AreEqual(false, lampDictionary[Detectors.livingRoomDetector].IsTurnedOn);
            //Assert.AreEqual(true, lampDictionary[Detectors.hallwayDetectorLivingRoom].IsTurnedOn);
            //Assert.AreEqual(true, lampDictionary[Detectors.hallwayDetectorToilet].IsTurnedOn);
            //scheduler.AdvanceJustAfter(TimeSpan.FromSeconds(4));
            //Assert.AreEqual(false, lampDictionary[Detectors.livingRoomDetector].IsTurnedOn);
            //Assert.AreEqual(false, lampDictionary[Detectors.hallwayDetectorLivingRoom].IsTurnedOn);
            //Assert.AreEqual(true, lampDictionary[Detectors.hallwayDetectorToilet].IsTurnedOn);
            //Assert.AreEqual(true, lampDictionary[Detectors.kitchenDetector].IsTurnedOn);
            //scheduler.AdvanceJustAfter(TimeSpan.FromSeconds(5));
            //Assert.AreEqual(false, lampDictionary[Detectors.livingRoomDetector].IsTurnedOn);
            //Assert.AreEqual(false, lampDictionary[Detectors.hallwayDetectorLivingRoom].IsTurnedOn);
            //Assert.AreEqual(false, lampDictionary[Detectors.hallwayDetectorToilet].IsTurnedOn);
            //Assert.AreEqual(true, lampDictionary[Detectors.kitchenDetector].IsTurnedOn);
        }
        public async Task WhenTwoPersonsStartsFromOneRoomAndSplitToTwoOthersNumbersOfPeopleShouldBeCorrect()
        {
            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithMotion
                                                           (
                OnNext(Time.Tics(1000), new MotionEnvelope(Detectors.livingRoomDetector)),
                OnNext(Time.Tics(2000), new MotionEnvelope(Detectors.hallwayDetectorLivingRoom)),
                OnNext(Time.Tics(2900), new MotionEnvelope(Detectors.bathroomDetector)),
                OnNext(Time.Tics(3000), new MotionEnvelope(Detectors.hallwayDetectorToilet)),
                OnNext(Time.Tics(4000), new MotionEnvelope(Detectors.kitchenDetector))
                                                           ).Build();

            scheduler.AdvanceJustAfter(TimeSpan.FromSeconds(4));

            var status = await _context.Query <MotionStatus>(MotionServiceStatusQuery.Create());

            Assert.AreEqual(1, await _context.Query <int>(NumberOfPeopleQuery.Create(Detectors.kitchenDetector)));
            Assert.AreEqual(1, await _context.Query <int>(NumberOfPeopleQuery.Create(Detectors.bathroomDetector)));
            //  Assert.AreEqual(2, status.NumberOfPersonsInHouse);
            Assert.AreEqual(true, lampDictionary[Detectors.kitchenDetector].IsTurnedOn);
            Assert.AreEqual(true, lampDictionary[Detectors.bathroomDetector].IsTurnedOn);
            Assert.AreEqual(false, lampDictionary[Detectors.hallwayDetectorLivingRoom].IsTurnedOn);
            //Assert.AreEqual(false, lampDictionary[Detectors.livingRoomDetector].IsTurnedOn);
            scheduler.AdvanceJustAfter(TimeSpan.FromSeconds(5));
            Assert.AreEqual(false, lampDictionary[Detectors.hallwayDetectorToilet].IsTurnedOn);
        }
        public async Task WhenCrossPassingNumberOfPeopleSlouldBeCorrect()
        {
            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithMotion
                                                           (
                OnNext(Time.Tics(500), new MotionEnvelope(Detectors.kitchenDetector)),
                OnNext(Time.Tics(501), new MotionEnvelope(Detectors.livingRoomDetector)),

                OnNext(Time.Tics(1500), new MotionEnvelope(Detectors.hallwayDetectorToilet)),
                OnNext(Time.Tics(1501), new MotionEnvelope(Detectors.hallwayDetectorLivingRoom)),

                //OnNext(Time.Tics(2000), new MotionEnvelope(HallwaylivingRoomDetector)), <- Undetected due motion detectors lag after previous move
                //OnNext(Time.Tics(2000), new MotionEnvelope(HallwaytoiletDetector)),     <- Undetected due motion detectors lag after previous move

                OnNext(Time.Tics(3000), new MotionEnvelope(Detectors.livingRoomDetector)),
                OnNext(Time.Tics(3001), new MotionEnvelope(Detectors.kitchenDetector))
                                                           ).Build();

            scheduler.AdvanceJustAfterEnd(motionEvents);

            var status = await _context.Query <MotionStatus>(MotionServiceStatusQuery.Create());

            var kitchen = await _context.Query <int>(NumberOfPeopleQuery.Create(Detectors.kitchenDetector));

            var living = await _context.Query <int>(NumberOfPeopleQuery.Create(Detectors.livingRoomDetector));

            Assert.AreEqual(1, kitchen);
            Assert.AreEqual(1, living);
            //Assert.AreEqual(2, status.NumberOfPersonsInHouse); //TODO
        }
        public async Task WhenTurnOnJustAfterTurnOffServiceShouldIncreaseTurnOffTimeout()
        {
            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithMotion
                                                           (
                OnNext(Time.Tics(500), new MotionEnvelope(Detectors.kitchenDetector)),
                OnNext(Time.Tics(12000), new MotionEnvelope(Detectors.kitchenDetector))
                                                           ).Build();

            scheduler.AdvanceJustAfterEnd(motionEvents);

            Assert.AreEqual(false, await _context.Query <bool>(AutomationStateQuery.Create(Detectors.kitchenDetector)));
        }
        public void WhenLeaveFromOnePersonRoomWithNoConfusionShouldTurnOffLightImmediately()
        {
            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithMotion
                                                           (
                OnNext(Time.Tics(500), new MotionEnvelope(Detectors.toiletDetector)),
                OnNext(Time.Tics(1500), new MotionEnvelope(Detectors.hallwayDetectorToilet))
                                                           ).Build();

            scheduler.AdvanceJustAfterEnd(motionEvents);

            Assert.AreEqual(false, lampDictionary[Detectors.toiletDetector].IsTurnedOn);
        }
        public async Task MoveInRoomShouldNotTurnOnLightWhenAutomationIsDisabled()
        {
            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithMotion
                                                           (
                OnNext(Time.Tics(500), new MotionEnvelope(Detectors.toiletDetector))
                                                           ).Build();

            _context.Send(DisableAutomationCommand.Create(Detectors.toiletDetector));
            scheduler.AdvanceToEnd(motionEvents);

            Assert.AreEqual(false, lampDictionary[Detectors.toiletDetector].IsTurnedOn);
            Assert.AreEqual(true, await _context.Query <bool>(AutomationStateQuery.Create(Detectors.toiletDetector)));
        }
        public void MoveInRoomShouldTurnOnLightWhenAutomationIsReEnabled()
        {
            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithMotion
                                                           (
                OnNext(Time.Tics(500), new MotionEnvelope(Detectors.toiletDetector)),
                OnNext(Time.Tics(2500), new MotionEnvelope(Detectors.toiletDetector))
                                                           ).Build();

            _context.Send(DisableAutomationCommand.Create(Detectors.toiletDetector));
            motionEvents.Subscribe(_ => _context.Send(EnableAutomationCommand.Create(Detectors.toiletDetector)));
            scheduler.AdvanceToEnd(motionEvents);

            Assert.AreEqual(true, lampDictionary[Detectors.toiletDetector].IsTurnedOn);
        }
        public void MoveInRoomShouldTurnOnLight()
        {
            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithMotion
                                                           (
                OnNext(Time.Tics(500), new MotionEnvelope(Detectors.toiletDetector)),
                OnNext(Time.Tics(1500), new MotionEnvelope(Detectors.kitchenDetector)),
                OnNext(Time.Tics(2000), new MotionEnvelope(Detectors.livingRoomDetector))
                                                           ).Build();

            scheduler.AdvanceToEnd(motionEvents);

            Assert.AreEqual(true, lampDictionary[Detectors.toiletDetector].IsTurnedOn);
            Assert.AreEqual(true, lampDictionary[Detectors.kitchenDetector].IsTurnedOn);
            Assert.AreEqual(true, lampDictionary[Detectors.livingRoomDetector].IsTurnedOn);
        }
        public void MoveInRoomShouldNotTurnOnLightOnNightWhenWorkinghoursAreDaylight()
        {
            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithWorkingTime(WorkingTime.DayLight).WithMotion
                                                           (
                OnNext(Time.Tics(500), new MotionEnvelope(Detectors.toiletDetector)),
                OnNext(Time.Tics(1500), new MotionEnvelope(Detectors.kitchenDetector)),
                OnNext(Time.Tics(2000), new MotionEnvelope(Detectors.livingRoomDetector))
                                                           ).Build();

            SystemTime.Set(TimeSpan.FromHours(21));

            scheduler.AdvanceToEnd(motionEvents);

            Assert.AreEqual(false, lampDictionary[Detectors.toiletDetector].IsTurnedOn);
            Assert.AreEqual(false, lampDictionary[Detectors.kitchenDetector].IsTurnedOn);
            Assert.AreEqual(false, lampDictionary[Detectors.livingRoomDetector].IsTurnedOn);
        }
        public async Task WhenNoMoveInRoomShouldTurnOffAfterTurnOffTimeout()
        {
            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithMotion
                                                           (
                OnNext(Time.Tics(500), new MotionEnvelope(Detectors.kitchenDetector))
                                                           ).Build();

            var area = await _context.Query <AreaDescriptor>(AreaDescriptorQuery.Create(Detectors.toiletDetector));

            scheduler.AdvanceJustAfterEnd(motionEvents);

            Assert.AreEqual(true, lampDictionary[Detectors.kitchenDetector].IsTurnedOn);
            scheduler.AdvanceTo(area.TurnOffTimeout);
            Assert.AreEqual(true, lampDictionary[Detectors.kitchenDetector].IsTurnedOn);
            scheduler.AdvanceJustAfter(area.TurnOffTimeout);
            Assert.AreEqual(false, lampDictionary[Detectors.kitchenDetector].IsTurnedOn);
        }
        public void WhenLeaveFromOnePersonRoomWithConfusionShouldTurnOffWhenConfusionResolved()
        {
            var confusionResolutionTime = TimeSpan.FromMilliseconds(5000);

            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithMotion
                                                           (
                OnNext(Time.Tics(500), new MotionEnvelope(Detectors.toiletDetector)),
                OnNext(Time.Tics(1000), new MotionEnvelope(Detectors.kitchenDetector)),
                OnNext(Time.Tics(1500), new MotionEnvelope(Detectors.hallwayDetectorToilet)),
                OnNext(Time.Tics(2000), new MotionEnvelope(Detectors.hallwayDetectorLivingRoom)),
                OnNext(Time.Tics(3000), new MotionEnvelope(Detectors.kitchenDetector))
                                                           ).Build();

            scheduler.AdvanceTo(confusionResolutionTime + TimeSpan.FromMilliseconds(1500));

            Assert.AreEqual(false, lampDictionary[Detectors.toiletDetector].IsTurnedOn);
        }
        public async Task MoveInFirstPathShouldNotConfusedNextPathWhenItIsSure()
        {
            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithMotion
                                                           (
                // First path
                OnNext(Time.Tics(500), new MotionEnvelope(Detectors.toiletDetector)),
                OnNext(Time.Tics(1500), new MotionEnvelope(Detectors.hallwayDetectorToilet)),
                OnNext(Time.Tics(2000), new MotionEnvelope(Detectors.kitchenDetector)),
                // Second path
                OnNext(Time.Tics(2500), new MotionEnvelope(Detectors.livingRoomDetector)),
                OnNext(Time.Tics(3000), new MotionEnvelope(Detectors.hallwayDetectorLivingRoom))
                                                           ).Build();

            scheduler.AdvanceJustAfterEnd(motionEvents);

            var status = await _context.Query <MotionStatus>(MotionServiceStatusQuery.Create());

            Assert.AreEqual(0, status.NumberOfConfusions);
            Assert.AreEqual(true, lampDictionary[Detectors.kitchenDetector].IsTurnedOn);
        }
        public async Task AnalyzeMoveShouldCountPeopleNumberInRoom()
        {
            var(motionEvents, scheduler, lampDictionary) = new LightAutomationServiceBuilder(_context).WithConfusionResolutionTime(TimeSpan.FromMilliseconds(5000))
                                                           .WithMotion
                                                           (
                OnNext(Time.Tics(500), new MotionEnvelope(Detectors.toiletDetector)),
                OnNext(Time.Tics(1500), new MotionEnvelope(Detectors.hallwayDetectorToilet)),
                OnNext(Time.Tics(2000), new MotionEnvelope(Detectors.kitchenDetector)),
                OnNext(Time.Tics(2500), new MotionEnvelope(Detectors.livingRoomDetector)),
                OnNext(Time.Tics(3000), new MotionEnvelope(Detectors.hallwayDetectorLivingRoom)),
                OnNext(Time.Tics(3500), new MotionEnvelope(Detectors.hallwayDetectorToilet)),
                OnNext(Time.Tics(4000), new MotionEnvelope(Detectors.kitchenDetector))
                                                           ).Build();

            scheduler.AdvanceTo(TimeSpan.FromMilliseconds(11000));

            var num = await _context.Query <int>(NumberOfPeopleQuery.Create(Detectors.kitchenDetector));

            Assert.AreEqual(2, num);
        }