package middleware

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

// RealMiddleware is a pair of
type RealMiddleware struct {
	Input  chan<- event.Event
	Output <-chan event.Event
}

// Middleware is a pointer of RealMiddleware
type Middleware *RealMiddleware

// Driver is Middleware constructor
type Driver func(config *interface{}) Middleware

// MiddlewareDrivers contains map from string to Drivers
var MiddlewareDrivers = map[string]Driver{
	"match":               match,
	"daily_report":        dailyReport,
	"serialize":           serializeDriver,
	"sql":                 sqlDriver,
	"combine":             combineDriver,
	"pass":                passDriver,
	"pipeline":            pipelineDriver,
	"foreach":             forEachDriver,
	"generate_exp_report": generateExpReportDriver,
	"update_notify_time":  updateNotifyTimeDriver,
	"get_undestroyed_abnormal_unalerted_experiments": getUndestroyedAbnormalUnalertedExperimentsDriver,
	"match_too_early_exp":                            matchTooEarlyExp,
	"destroy_exp":                                    destroyExpDriver,
	"generate_destroy_alert":                         destroyAlert,
	"log":                                            logDriver,
	"slack":                                          slackDriver,
	"schedule":                                       schedule,
}

// Middlewares map middleware name to middleware
var Middlewares = make(map[string]Middleware)

// ConstructMiddlewares will construct all sinks from config
func ConstructMiddlewares(config config.Config) {
	if config.Middleware == nil {
		log.Warning("No middleware has been configured")
	}

	for _, middlewareConfig := range *config.Middleware {
		if middlewareConfig.Driver == nil {
			log.Errorf("Driver of %s is not set. There is a bug while setting default driver", middlewareConfig.Name)
			return
		}
		driver, ok := MiddlewareDrivers[*middlewareConfig.Driver]
		if !ok {
			log.Errorf("Driver %s cannot be found", *middlewareConfig.Driver)
			return
		}
		Middlewares[middlewareConfig.Name] = driver(middlewareConfig.Config)
	}
}
