package spade

import "time"

// Reporter sends metrics on events
type Reporter interface {
	// RequestCount is called any time a spade request is made
	RequestCount()
	// SendSuccess is called when a successful spade request happens. The HTTP response is an 204 (NoContent)
	SendSuccess(duration time.Duration)
	// SendFailure is called when a spade request fails for any reason
	SendFailure(duration time.Duration, err error)
	// Events is called with the number of events sent in a successful request
	Events(eventCount int)
	// BacklogFull is called when the backlog is full and cannot queue more events
	BacklogFull()
}

type noopReporter struct{}

func (*noopReporter) RequestCount()                        {}
func (*noopReporter) SendSuccess(_ time.Duration)          {}
func (*noopReporter) SendFailure(_ time.Duration, _ error) {}
func (*noopReporter) Events(_ int)                         {}
func (*noopReporter) BacklogFull()                         {}

var _ Reporter = (*noopReporter)(nil)

// MultiReporter chains together multiple reporters
type MultiReporter struct {
	Reporters []Reporter
}

// RequestCount is called any time a spade request is made
func (m *MultiReporter) RequestCount() {
	for _, reporter := range m.Reporters {
		reporter.RequestCount()
	}
}

// SendSuccess is called when a successful spade request happens. The HTTP response is an 204 (NoContent)
func (m *MultiReporter) SendSuccess(duration time.Duration) {
	for _, reporter := range m.Reporters {
		reporter.SendSuccess(duration)
	}
}

// SendFailure is called when a spade request fails for any reason
func (m *MultiReporter) SendFailure(duration time.Duration, err error) {
	for _, reporter := range m.Reporters {
		reporter.SendFailure(duration, err)
	}
}

// Events is called with the number of events sent in a successful request
func (m *MultiReporter) Events(eventCount int) {
	for _, reporter := range m.Reporters {
		reporter.Events(eventCount)
	}
}

// BacklogFull is called when the backlog is full and cannot queue more events
func (m *MultiReporter) BacklogFull() {
	for _, reporter := range m.Reporters {
		reporter.BacklogFull()
	}
}

var _ Reporter = (*MultiReporter)(nil)
