package elasticache

import (
	"context"
	"log"
	"strconv"
	"time"

	"code.justin.tv/common/config"

	"github.com/bradfitz/gomemcache/memcache"
	"github.com/pkg/errors"
)

// Memcache interface we actually use.
type Memcache interface {
	Add(item *memcache.Item) error
	Delete(key string) error
	Get(key string) (item *memcache.Item, err error)
	GetMulti(keys []string) (map[string]*memcache.Item, error)
	Set(item *memcache.Item) error
	Touch(key string, seconds int32) (err error)
}

func init() {
	config.Register(map[string]string{
		"memcached-timeout-ms": "1000",
	})
}

// New constructs a memcache Client with ElastiCache auto-discovery.
// Every minute, the ElastiCache configuration endpoint will be polled to
// update the list of available memcache servers.
func New(endpoint string) (*memcache.Client, error) {
	return NewWithContext(context.Background(), endpoint)
}

// NewWithContext accepts a context so you can stop the poller.
// Cancelling the context will stop the poller.
func NewWithContext(ctx context.Context, endpoint string) (*memcache.Client, error) {
	ss := new(memcache.ServerList)

	poller := NewPoller(endpoint, ss)
	if err := poller.Start(ctx); err != nil {
		return nil, err
	}

	client := memcache.NewFromSelector(ss)

	timeoutMS, err := strconv.Atoi(config.MustResolve("memcached-timeout-ms"))
	if err != nil {
		log.Fatal(errors.Wrapf(err, "Error parsing memcached-timeout-ms flag"))
	}
	client.Timeout = time.Duration(timeoutMS) * time.Millisecond

	return client, nil
}
