package sqsclient

import (
	"time"

	"github.com/aws/aws-sdk-go/aws/client"
	"github.com/aws/aws-sdk-go/service/sqs/sqsiface"

	eventbus "code.justin.tv/eventbus/client"
)

type Config struct {
	Session    client.ConfigProvider // Required: aws config provider or session
	Dispatcher eventbus.Dispatcher   // Required: a dispatcher to call for each message
	QueueURL   string                // Required: the URL of the queue to consume

	// Basic tuning
	VisibilityTimeout  time.Duration // Default: 30 seconds
	MinPollers         int           // Goroutines simultaneously polling at start (Default: 2)
	DeliverConcurrency int           // How many goroutines to dispatch with (Default: 100)

	// Used to provide a callback that is fired for internal poller events.
	// This is not required, but can be used to provide visibility into what
	// is happening at runtime such as scaleup, temporary network errors, etc.
	HookCallback func(HookEvent)

	// Fine Tuning variables, probably can be left at defaults
	FineTuning

	// WARNING: Passing a custom sqs client will have no guarantees that necessary permissions are
	// available in the client's account. It is advised to simply pass us the session which will
	// be used to create credentials for assuming the necessary roles!
	OverrideClient sqsiface.SQSAPI
}

type FineTuning struct {
	DeliverChannelDepth int // How deep the channel is to buffer deliveries. (Default: 100)
	AckChannelDepth     int // How deep the channel is to buffer acks (Default: DeliverConcurrency)

	// During shutdown, we normally wait for all outgoing requests to complete and
	// all outgoing dispatches to complete. After this duration however, we will
	// cancel all outgoing requests to hasten shutdown (Default: 30 sec)
	ShutdownCancelRequests time.Duration
}

func (config *Config) setDefaults() {
	if config.MinPollers <= 0 {
		config.MinPollers = 2
	}
	if config.DeliverConcurrency <= 0 {
		config.DeliverConcurrency = 100
	}
	if config.VisibilityTimeout <= 0 {
		config.VisibilityTimeout = 30 * time.Second
	}

	if config.HookCallback == nil {
		config.HookCallback = DefaultHookCallback
	}

	// fine tuning

	ft := &config.FineTuning
	if ft.DeliverChannelDepth <= 0 {
		ft.DeliverChannelDepth = 100
	}
	if ft.AckChannelDepth <= 0 {
		ft.AckChannelDepth = config.DeliverConcurrency
	}
	if ft.ShutdownCancelRequests <= 0 {
		ft.ShutdownCancelRequests = 30 * time.Second
	}
}
