package middleware

import (
	"github.com/ngaut/log"
	"github.com/pingcap/schrodinger/notifiermgr/event"
)

// Pipe will pipe several middleware together and return a new Middleware
func Pipe(middlewares []Middleware) Middleware {
	go func() {
		for index, middleware := range middlewares {
			index := index
			middleware := middleware
			if index < len(middlewares)-1 {
				go func() {
					if middleware == nil {
						log.Error("Please check error while constructing middleware")
						return
					}
					for event := range (*middleware).Output {
						if middlewares[index+1] == nil {
							log.Error("Please check error while constructing middleware")
							return
						}
						(*middlewares[index+1]).Input <- event
					}
				}()
			}
		}
	}()

	return &RealMiddleware{
		Input:  middlewares[0].Input,
		Output: middlewares[len(middlewares)-1].Output,
	}
}

func pipelineDriver(configPtr *interface{}) Middleware {
	input := make(chan event.Event)
	output := make(chan event.Event)

	if configPtr == nil {
		log.Error("Config in pipeline driver is nil")
		return nil
	}

	middlewareNames, ok := (*configPtr).([]interface{})
	if !ok {
		log.Errorf("config of pipeline is not a list of string but %T", *configPtr)
	}

	go func() {
		var middleware Middleware

		inited := false
		for ev := range input {
			if !inited {
				middlewares := make([]Middleware, len(middlewareNames))
				err := loadFromNames(&middlewares, middlewareNames)
				if err != nil {
					log.Error(err)
					return
				}

				middleware = Pipe(middlewares)

				go func() {
					for ev := range (*middleware).Output {
						output <- ev
					}
				}()
				inited = true
			}
			(*middleware).Input <- ev
		}
	}()
	return &RealMiddleware{
		input,
		output,
	}
}
