package events

import (
	"context"
	"encoding/json"

	"code.justin.tv/sse/malachai/pkg/internal/closer"
	"code.justin.tv/sse/malachai/pkg/log"
	"github.com/cactus/go-statsd-client/statsd"
)

// Logger describes an event logger
type Logger interface {
	Run()
	WriteEvent(interface{})
	WithFields(DefaultableEvent) EventWriter
}

// BatchShipper ships logs to firehose
type BatchShipper interface {
	Add(context.Context, []byte) error
	Run()
	SetStatter(statsd.Statter)
}

// Client writes events directly to firehose
type Client struct {
	BatchShipper BatchShipper
	Closer       *closer.Closer
	Logger       log.S2SLogger
	cfg          Config
}

// Run starts the background updater
func (c *Client) Run() {
	if c.Closer == nil {
		c.Closer = closer.New()
	}
	c.BatchShipper.Run()
}

// Close closes the client
func (c *Client) Close() error {
	return c.Closer.Close()
}

// WriteEvent writes a list of events to file
func (c *Client) WriteEvent(event interface{}) {
	var (
		raw []byte
		err error
	)

	if raw, err = json.Marshal(event); err != nil {
		c.Logger.Errorf("error marshaling event for logs: %s", err.Error())
	}

	if err = c.BatchShipper.Add(context.Background(), append(raw, []byte("\n")...)); err != nil {
		c.Logger.Errorf("error writing event to logs: %s", err.Error())
	}
}

// WithStatter sets a statter
func (c *Client) WithStatter(statter statsd.Statter) EventWriterClient {
	c.BatchShipper.SetStatter(statter)
	return c
}

// WithFields wraps this client in a client that provides defaults
func (c *Client) WithFields(defaults DefaultableEvent) EventWriter {
	return &WithFieldsEventWriter{
		EventWriter:   c,
		EventDefaults: defaults,
	}
}
