package metrics

import (
	"context"
	"sync"

	log "github.com/Sirupsen/logrus"

	pb "code.justin.tv/dta/rockpaperscissors/proto"
)

var (
	r    *Singleton
	once sync.Once
)

// Calculator is the interface that all registered caculators must implement.
type Calculator interface {
	Calculate(ctx context.Context, req *pb.GetMetricRequest, resp *pb.GetMetricResponse) error
}

// CalculatorFactory is the interface for how to initialize new calculators.
type CalculatorFactory func(pb.ProjectMetadataServiceServer, pb.EventServiceServer) (Calculator, error)

type registryEntry struct {
	Info    *pb.MetricInfo
	Factory CalculatorFactory
}

// Singleton is the registry singleton, get the instance with Registry().
type Singleton map[string]registryEntry

// Registry returns the registry singleton.
func Registry() *Singleton {
	once.Do(func() {
		s := make(Singleton)
		r = &s
	})
	return r
}

// Register a metrics calculator into registry.
func (r *Singleton) Register(info *pb.MetricInfo, factory CalculatorFactory) {
	(*r)[info.MetricId] = registryEntry{Info: info, Factory: factory}
	log.Infof("Registered metric calculator: %s", info.MetricId)
}
