//
// An MTA Provider is expected to report EK_FATAL
// right before it shuts down.
//
//  Unit under test: Any MTAProvider
//
//
func Test_check_fatal_event_on_shutdown(t *testing.T) {
	c := make(chan int)
	events := make([]mtacontainer.Event, 0)
	provider := loopbackprovider.New(utilities.GetLogger("Loop"), NewMockFailureStrategy())

	go func() {
		for {
			select {
			case e := <-provider.GetEvent():
				events = append(events, e)
			case <-c:
				return
			}
		}
	}()

	provider.Stop()

	if len(events) == 0 {
		t.Error("Expected at least one event EK_FATAL event...")
	}
	c <- 0

	foundFatal := false
	for i := range events {
		if events[i].GetKind() == mtacontainer.EK_FATAL {
			foundFatal = true
		}
	}

	if foundFatal == false {
		t.Error("Expected one fatal event")
	}
}
// ------------------------------------------
//
//
// End 2 End test of the MTAContainer with Failure strategy
// and RoundRobinSchedule.
//
//
func TestEnd2End(t *testing.T) {

	//	mg := mailgunprovider.New(utilities.GetLogger("MG"),mailgunprovider.BitLabConfig("09fe27"),NewMockFailureStrategy());
	//	az := amazonsesprovider.New(utilities.GetLogger("MG"),amazonsesprovider.BitLabConfig("09fe27"),NewMockFailureStrategy());
	//  sg := sendgridprovider.New(utilities.GetLogger("MG"),sendgridprovider.BitLabConfig("09fe27"),NewMockFailureStrategy());
	var provider = loopbackprovider.New(utilities.GetLogger("loop1"), mtacontainer.NewThressHoldFailureStrategy(12))

	scheduler := mtacontainer.NewRoundRobinScheduler([]mtacontainer.MTAProvider{provider})

	container := mtacontainer.New(scheduler)

	mail1 := FreshTestMail(provider, "*****@*****.**")
	mail2 := FreshTestMail(provider, "*****@*****.**")
	mail3 := FreshTestMail(provider, "*****@*****.**")

	container.GetOutgoing() <- mail1
	container.GetOutgoing() <- mail2
	container.GetOutgoing() <- mail3

	go func() {
		<-container.GetIncoming()
	}()

	i := 0
	for {
		select {
		case e := <-container.GetEvent():
			log.Println("Reading event from container: " + e.GetError().Error())
			if i == 2 {
				return
			}
			i = i + 1
		}
	}
}
func Test_one_failover(t *testing.T) {

	loop1 := loopbackprovider.New(utilities.GetLogger("loop1"), new(FailImmediatelyFailureStrategy))
	loop2 := loopbackprovider.New(utilities.GetLogger("loop2"), NewMockFailureStrategy())

	scheduler := mtacontainer.NewRoundRobinScheduler([]mtacontainer.MTAProvider{loop1, loop2})

	container := mtacontainer.New(scheduler)

	mail := FreshTestMail(loop1, "*****@*****.**")

	go func() {
		container.GetOutgoing() <- mail
		for {
			select {
			case evt := <-container.GetEvent():
				log.Println(evt.GetError().Error())
			}
		}
	}()

	// the round robin scheduler will schedule {loop1} which fails immediately
	// we expect to see {mail} emerge on the {GetIncoming} channel of {loop2}
	// because it has been RESUBMITTET to {loop2} by the fail over mechanism in
	// the MTAContainer.

	mailPrime, ok := <-loop2.GetIncoming()

	if ok == false {
		t.Error("loop2 incoming failed to provide emai.")
	}

	if mailPrime != mail {
		t.Error("Wrong mail")
	}
}
func Test_all_failover(t *testing.T) {

	loop1 := loopbackprovider.New(utilities.GetLogger("loop1"), new(FailImmediatelyFailureStrategy))

	scheduler := mtacontainer.NewRoundRobinScheduler([]mtacontainer.MTAProvider{loop1})

	container := mtacontainer.New(scheduler)

	go func() {
		mail := FreshTestMail(loop1, "*****@*****.**")
		container.GetOutgoing() <- mail
		for {
			select {
			case evt := <-container.GetEvent():
				log.Println(evt.GetError().Error())
			}
		}
	}()

}
func TestLoopBack(t *testing.T) {

	loop1 := loopbackprovider.New(utilities.GetLogger("loop1"), mtacontainer.NewThressHoldFailureStrategy(1))

	mail := test.FreshTestMail(loop1, "test")

	c := make(chan int)

	go func() {
		for {
			select {
			case <-loop1.GetEvent():
			case <-c:
			}
		}
	}()

	loop1.GetOutgoing() <- mail

	<-loop1.GetIncoming()
}
func GetLoopBackContainer() (mtacontainer.MTAContainer, mtacontainer.Scheduler) {
	var provider = loopbackprovider.New(utilities.GetLogger("LoopBack"), mtacontainer.NewThressHoldFailureStrategy(ERROR_THRESHOLD))
	var scheduler = mtacontainer.NewRoundRobinScheduler([]mtacontainer.MTAProvider{provider})
	return mtacontainer.New(scheduler), scheduler
}