/// <summary>
        /// Calls the subscriber service.
        /// </summary>
        /// <param name="subscriber">The subscriber.</param>
        public void CallSubscriberService(Subscriber subscriber)
        {
            bool passed;

            passed = ServicePollPassed(subscriber);
            if (!passed)
            {
                if (!ServiceOutage(subscriber.Service))
                {
                    // check for the  grace time ??
                    // if exist wait before notification send
                    // check to see if service online before end of gracetime
                    // if grace time < polling frequency extra check is required

                    if (subscriber.GraceTime > 0)
                    {
                        Thread.Sleep(subscriber.GraceTime);
                        passed = ServicePollPassed(subscriber);
                        if (subscriber.GraceTime < subscriber.PollingFrequency)
                        {
                            passed = ServicePollPassed(subscriber);
                        }
                        if (!passed)
                        {
                            _notification.Send(subscriber.Service.Ip, subscriber.Service.Port);
                        }
                    }
                    else
                    {
                        _notification.Send(subscriber.Service.Ip, subscriber.Service.Port);
                    }
                }
            }
        }
        public void AddToSubscriptionList_registers_a_new_Subscriber()
        {
            var sub = new Subscriber
            {
                Id = 1,
                Name = "Nino"
            };

            var allsubs = _notification.GetSubscriptionList();

            Assert.IsTrue(!allsubs.Any());
            _notification.AddToSubscriptionList(sub);
            Assert.IsTrue(allsubs.Count() == 1);
        }
        /// <summary>
        /// Enables the specified caller.
        /// </summary>
        /// <param name="caller">The caller.</param>
        /// <exception cref="System.ArgumentNullException">caller</exception>
        public void Enable(Subscriber caller)
        {
            if(caller == null)
                throw new ArgumentNullException("caller");

            var allServices = _nodeProvider.GetAllAvailableServices();

            // we should check if service is not already available
            // otherwize just add the caller to notification list
            var serviceExist = allServices.Any(a => a.Ip == caller.Service.Ip && a.Port == caller.Service.Port);

            // either case the caller gets registered for notifications
            _notification.AddToSubscriptionList(caller);

            if (!serviceExist)
            {
                // if service does not exist, add to the service list
                _nodeProvider.AddService(caller.Service);
                var timer = new Timer(o => _connection.CallSubscriberService(caller), null, 0, caller.PollingFrequency);
            }
        }
        public void CallSubscribedServies_sends_notification_on_Failure()
        {
            var thisSubsriber = new Subscriber
                        {
                            PollingFrequency = 100000,
                            Service = new Node
                                {
                                    Ip = "127.0.0.1",
                                    Port = 11111,
                                    OutageStartTime = DateTime.Now,
                                    OutageEndTime = DateTime.Now.AddHours(-1)
                                }

                };

            _notification.Expect(a => a.GetSubscriptionList()).Return(GetSubscribers());
            _connection.CallSubscriberService(thisSubsriber);
            _notification.AssertWasCalled(
                a =>
                a.Send(thisSubsriber.Service.Ip, thisSubsriber.Service.Port));
        }
        public void Enable_only_calls_CallSubscriberService_for_newServices()
        {
            var nodeList = new List<Node>
                {
                    new Node
                        {
                            Ip = "127.0.0.1",
                            Port = 11112,
                        }
                };

            var sub = new Subscriber
                {
                    Service = nodeList.First()
                };

            _nodeProvider.Expect(a => a.GetAllAvailableServices()).Return(nodeList);
            _register.Enable(sub);

            // passing same service
            _connection.AssertWasNotCalled(a => a.CallSubscriberService(sub));
        }
        /// <summary>
        /// Services the poll passed.
        /// </summary>
        /// <param name="subscriber">The subscriber.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">criteria</exception>
        /// <exception cref="System.IO.InvalidDataException">Ip</exception>
        /// <exception cref="System.ArgumentOutOfRangeException">frequency most be higher than a second</exception>
        public bool ServicePollPassed(Subscriber subscriber)
        {
            if (subscriber.Service == null)
                throw new ArgumentNullException("criteria");

            if(!IsIPV4(subscriber.Service.Ip))
                throw new InvalidDataException("Ip");

            if (subscriber.PollingFrequency < MIN_FREQUENCY)
                throw new ArgumentOutOfRangeException("frequency most be higher than a second");

            while (true)
            {
                try
                {
                    TryConnect(subscriber.Service);
                }
                catch (Exception)
                {
                    return false;
                }

                var reader = new StreamReader(_client.GetStream());
                string line = string.Empty;

                while (TestConnection(subscriber.PollingFrequency))
                {
                    try
                    {
                        // this is how we check to see if conection is still online
                        line = reader.ReadLine();
                    }
                    catch
                    {
                        return false;
                    }
                }
            }
        }
        public void Enable_Will_calls_all_expected_services_for_newServices()
        {
            var nodeList = new List<Node>
                {
                    new Node
                        {
                            Ip = "192.168.0.1",
                            Port = 11112,
                        }
                };

            var sub = new Subscriber
            {
                Service = GetTestSubscribers().First().Service
            };

            _nodeProvider.Expect(a => a.GetAllAvailableServices()).Return(nodeList);
            _register.Enable(sub);

            // passing same service
            _connection.AssertWasCalled(a => a.CallSubscriberService(sub));
            _nodeProvider.AssertWasCalled(a => a.AddService(sub.Service));
        }
 /// <summary>
 /// Adds to subscription list.
 /// </summary>
 /// <param name="caller">The caller.</param>
 public void AddToSubscriptionList(Subscriber caller)
 {
     SubscriptionList.Add(caller);
 }