package metrics

import (
	"net/http"

	telemetry "code.justin.tv/amzn/TwitchTelemetry"
	metricsmiddleware "code.justin.tv/amzn/TwitchTelemetryMetricsMiddleware"
	"code.justin.tv/video/metrics-middleware/v2/operation"
	"code.justin.tv/video/metrics-middleware/v2/twirpmetric"
)

// NewTwirpServerMiddleware creates a struct that can be used to add middleware to an Twirp server
// that sends metrics on operations to CloudWatch.
func NewTwirpServerMiddleware(sampleReporter telemetry.SampleReporter) *twirpmetric.Server {
	opMonitor := &metricsmiddleware.OperationMonitor{
		SampleReporter: sampleReporter,
		AutoFlush:      false,
		MonitorConfig: metricsmiddleware.MonitorConfig{
			TwirpErrorCodes: true,
		},
	}
	opStarter := &operation.Starter{
		OpMonitors: []operation.OpMonitor{
			opMonitor,
		},
	}
	return &twirpmetric.Server{
		Starter: opStarter,
	}
}

type TwirpClientMiddlewareWrapperConfig struct {
	SampleReporter *telemetry.SampleReporter

	// Whether telemetry should send metrics after every request.
	// This should usually be set to false so that telemetry can buffer metrics.
	AutoFlush bool
}

// Creates a function that takes a round tripper, and wraps it in twirp client middleware.
func NewTwirpClientMiddlewareWrapper(conf *TwirpClientMiddlewareWrapperConfig) WrapperFunc {
	return func(rt http.RoundTripper) http.RoundTripper {
		opMonitor := &metricsmiddleware.OperationMonitor{
			SampleReporter: *conf.SampleReporter,
			AutoFlush:      conf.AutoFlush,
			MonitorConfig: metricsmiddleware.MonitorConfig{
				TwirpErrorCodes: true,
			},
		}
		opStarter := &operation.Starter{
			OpMonitors: []operation.OpMonitor{
				opMonitor,
			},
		}

		return &twirpmetric.Client{
			Transport: rt,
			Starter:   opStarter,
		}
	}
}
