func main() {
	processorFlagPtr := flag.Bool("processor", false, "by default it starts an http server instance, use this flag to start a processor instead")
	envFlagPtr := flag.String("env", "DEV", "by default the environnement is set to DEV, use PROD for production")
	flag.Parse()

	config, err := utilities.LoadJSONConfig()
	if err != nil {
		log.Fatalf("FATAL ERROR: reading json config: %s", err.Error())
	}

	queueConn, err := amqp.Dial(config.QueueConnectionUrl)
	if err != nil {
		log.Fatalf("FATAL ERROR: initializing persistent queue connection: %s", err.Error())
	}
	defer queueConn.Close()

	trackingValidator, err := validators.NewJSONEventTrackingValidator()
	if err != nil {
		log.Fatalf("FATAL ERROR: initializing tracking validator: %s", err.Error())
	}

	if *processorFlagPtr {
		cluster := gocql.NewCluster(strings.Split(config.StorageDbParams.ClusterUrls, "|")...)
		cluster.Keyspace = config.StorageDbParams.Keyspace
		cluster.Authenticator = gocql.PasswordAuthenticator{
			Username: config.StorageDbParams.Username,
			Password: config.StorageDbParams.Password,
		}
		storageConn, err := datastores.NewStorageInstance(cluster)
		if err != nil {
			log.Fatalf("FATAL ERROR: initializing storage db connection: %s", err.Error())
		}

		context := ctx.NewContext(
			nil,
			storageConn,
			queues.NewRabbitMQConnection(queueConn),
			trackingValidator,
			*envFlagPtr)

		startProcessingServer(context)
	} else {
		authDb, err := sql.Open("mysql", config.AuthDbConnectionString)
		if err != nil {
			log.Fatalf("FATAL ERROR: initializing database connection: %s", err.Error())
		}
		defer authDb.Close()

		context := ctx.NewContext(
			datastores.NewAuthInstance(authDb),
			nil,
			queues.NewRabbitMQConnection(queueConn),
			trackingValidator,
			*envFlagPtr)

		startTrackingServer(context)
	}
}
func init() {
	mockedDb, err := sqlmock.New()
	if err != nil {
		log.Fatalf("An error: %s, was not expected when opening a stub database connection", err.Error())
	}

	columns := []string{"exists"}
	sqlmock.ExpectQuery("SELECT EXISTS\\(SELECT id FROM api_tokens WHERE token = (.+)\\)").
		WithArgs("123").
		WillReturnRows(sqlmock.NewRows(columns).AddRow(false))

	sqlmock.ExpectQuery("SELECT EXISTS\\(SELECT id FROM api_tokens WHERE token = (.+)\\)").
		WithArgs("456").
		WillReturnRows(sqlmock.NewRows(columns).AddRow(true))

	trackingValidator, err := validators.NewJSONEventTrackingValidator()
	if err != nil {
		log.Fatalf("An error: %s, was not expected when initializing tracking validator", err.Error())
	}

	router = mux.NewRouter()
	context := ctx.NewContext(datastores.NewAuthInstance(mockedDb), nil, nil, trackingValidator, "DEV")
	testHandler := ctx.NewHandler(context, testHandle)
	testFinalHander := ctx.NewFinalHandler(context, []byte(""), testFinalHandle)

	router.Handle("/testEnforceJSON", middlewares.EnforceJSONHandler(testHandler))
	router.Handle("/testAuth", middlewares.AuthHandler(testHandler))
	router.Handle("/testValidateEventTrackingPayloadHandler", middlewares.ValidateEventTrackingPayloadHandler(testFinalHander))

	server = httptest.NewServer(router)

	testEnforceJSONUrl = fmt.Sprintf("%s/testEnforceJSON", server.URL)
	testAuthUrl = fmt.Sprintf("%s/testAuth", server.URL)
	testValidateEventTrackingPayloadHandlerUrl = fmt.Sprintf("%s/testValidateEventTrackingPayloadHandler", server.URL)
}