package twitchclient

import "context"

// ReqOpts contains common request options used to interface with Twitch services.
type ReqOpts struct {
	// AuthorizationToken is the token received from our Authorization service
	// which can be forwarded to other Twitch services. Do not set this if
	// the request leaves the Twitch infrastructure.
	AuthorizationToken string

	// ClientID is the alphanumeric ID of the client making the request.
	ClientID string

	// ClientRowID is the database row ID of the client making the request.
	ClientRowID string

	// Enables request timing stats, which are in the format:
	//    [{StatNamePrefix}.]{StatName}.{RespStatusCode}
	// The StatNamePrefix is part of ClientConf and is optional.
	// The RespStatusCode is the response status, or 0 for errors.
	// The sample rate depends on the StatSampleRate option, being 0.1 by default.
	StatName string

	// Sample rate for both request timing stats and http tracing stats.
	// Defaults to 0.1
	StatSampleRate float32
}

var reqOptsCtxKey = new(int)

// WithReqOpts merges options for the request into the context.
// If the context already had options, only new non-zero values are set, others are left as defaults.
func WithReqOpts(ctx context.Context, reqOpts ReqOpts) context.Context {
	if defaults, ok := ctx.Value(reqOptsCtxKey).(ReqOpts); ok {
		reqOpts = (&reqOpts).WithDefaults(defaults)
	}
	return context.WithValue(ctx, reqOptsCtxKey, reqOpts)
}

// GetReqOpts returns the ReqOpts from the context.
func GetReqOpts(ctx context.Context) ReqOpts {
	if reqOpts, ok := ctx.Value(reqOptsCtxKey).(ReqOpts); ok {
		return reqOpts
	}
	return ReqOpts{}
}

// WithClearReqOpts can be used to reset previous options in the context back to zero values.
func WithClearReqOpts(ctx context.Context) context.Context {
	return context.WithValue(ctx, reqOptsCtxKey, ReqOpts{})
}

// WithDefaults returns a copy with defaults instead of zero-values.
func (opts *ReqOpts) WithDefaults(defaults ReqOpts) ReqOpts {
	if opts == nil {
		return defaults
	}

	if opts.AuthorizationToken != "" {
		defaults.AuthorizationToken = opts.AuthorizationToken
	}
	if opts.ClientID != "" {
		defaults.ClientID = opts.ClientID
	}
	if opts.ClientRowID != "" {
		defaults.ClientRowID = opts.ClientRowID
	}
	if opts.StatName != "" {
		defaults.StatName = opts.StatName
	}
	if opts.StatSampleRate != 0 {
		defaults.StatSampleRate = opts.StatSampleRate
	}
	return defaults
}

// MergeReqOpts returns a copy with defaults instead of zero-values.
// Merges opts into defaults, not the other way around. Please use opts.WithDefaults(defaults) instead.
func MergeReqOpts(opts *ReqOpts, defaults ReqOpts) ReqOpts {
	return opts.WithDefaults(defaults)
}
