text: ﻿using System;
  using System.Collections.Generic;
  using System.Threading.Tasks;
  using EasyNetQ;
  using EasyNetQ.FluentConfiguration;
  using NSubstitute;
  using Revo.Core.Events;
  using Revo.EasyNetQ.Configuration;
  using Xunit;
  
  namespace Revo.EasyNetQ.Tests
  {
      public class BusInitializerTests
      {
          private BusInitializer sut;
          private EasyNetQConfigurationSection configurationSection;
          private IBus bus;
          private IEasyNetQSubscriptionHandler subscriptionHandler;
  
          public BusInitializerTests()
          {
              configurationSection = new EasyNetQConfigurationSection();
              bus = Substitute.For<IBus>();
              subscriptionHandler = Substitute.For<IEasyNetQSubscriptionHandler>();
  
              sut = new BusInitializer(bus, subscriptionHandler, configurationSection);
          }
  
          [Fact]
          public void OnApplicationStarted_Subscribes()
          {
              configurationSection.Subscriptions
                  .AddType<Event1>("sub1", null)
                  .AddType<Event2>("sub2", null);
  
              sut.OnApplicationStarted();
              
              bus.Received(1).SubscribeAsync<IEventMessage<Event1>>("sub1", Arg.Any<Func<IEventMessage<Event1>, Task>>(), Arg.Any<Action<ISubscriptionConfiguration>>());
              bus.Received(1).SubscribeAsync<IEventMessage<Event2>>("sub2", Arg.Any<Func<IEventMessage<Event2>, Task>>(), Arg.Any<Action<ISubscriptionConfiguration>>());
          }
  
          [Fact]
          public void OnApplicationStarted_HandleMessage()
          {
              configurationSection.Subscriptions
                  .AddType<Event1>("sub1", null);
  
              Dictionary<string, Func<IEventMessage<Event1>, Task>> handleActions = new Dictionary<string, Func<IEventMessage<Event1>, Task>>();
              bus.WhenForAnyArgs(x => x.SubscribeAsync<IEventMessage<Event1>>(null, null, null))
                  .Do(ci => handleActions[ci.ArgAt<string>(0)] = ci.ArgAt<Func<IEventMessage<Event1>, Task>>(1));
              
              sut.OnApplicationStarted();
  
              var subCfg1 = Substitute.For<ISubscriptionConfiguration>();
  
              var message = Substitute.For<IEventMessage<Event1>>();
              handleActions["sub1"](message);
              subscriptionHandler.Received(1).HandleMessage(message);
          }
  
          [Fact]
          public void OnApplicationStarted_ConfigurationAction()
          {
              var cfgAction1 = Substitute.For<Action<ISubscriptionConfiguration>>();
              configurationSection.Subscriptions
                  .AddType<Event1>("sub1", cfgAction1)
                  .AddType<Event2>("sub2", null);
              
              Dictionary<string, Action<ISubscriptionConfiguration>> configActions = new Dictionary<string, Action<ISubscriptionConfiguration>>();
              bus.WhenForAnyArgs(x => x.SubscribeAsync<IEventMessage<Event1>>(null, null, null))
                  .Do(ci => configActions[ci.ArgAt<string>(0)] = ci.ArgAt<Action<ISubscriptionConfiguration>>(2));
              bus.WhenForAnyArgs(x => x.SubscribeAsync<IEventMessage<Event2>>(null, null, null))
                  .Do(ci => configActions[ci.ArgAt<string>(0)] = ci.ArgAt<Action<ISubscriptionConfiguration>>(2));
              
              sut.OnApplicationStarted();
  
              var subCfg1 = Substitute.For<ISubscriptionConfiguration>();
              configActions["sub1"](subCfg1);
              cfgAction1.Received(1).Invoke(subCfg1);
              
              var subCfg2 = Substitute.For<ISubscriptionConfiguration>();
              configActions["sub2"](subCfg2);
          }
  
          public class Event1 : IEvent
          {
          }
  
          public class Event2 : IEvent
          {
          }
      }
  }
  