package twitchstats

import (
	"net/http"
	"sync"
	"time"
)

type Event struct {
	Client        *http.Client
	eventName     string
	stats         *Stats
	data          map[string]interface{}
	startTime     time.Time
	finishTime    time.Time
	subTaskStart  map[string]time.Time
	subTaskFinish map[string]time.Time
	mutex         sync.Mutex
	sendFinish    sync.Once
}

// Start will start the timer for the event. This is generally not needed as
// stats.NewEvent will automatically call it. This is only needed for precision
// timing.
func (e *Event) Start() {
	e.startTime = time.Now()
}

// StartSubTask will start a new subtask.
func (e *Event) StartSubTask(name string) {
	e.mutex.Lock()
	defer e.mutex.Unlock()

	e.subTaskStart[name] = time.Now()
}

// FinishSubTask will mark a sub task as finished. It can be called multiple
// times (to allow defer and early returns) but will only keep the first
// result.
func (e *Event) FinishSubTask(name string) {
	e.mutex.Lock()
	defer e.mutex.Unlock()

	if _, ok := e.subTaskFinish[name]; !ok {
		e.subTaskFinish[name] = time.Now()
	}
}

// Finish will mark an event as finished and send any data to mixpanel.
func (e *Event) Finish() error {
	e.mutex.Lock()
	defer e.mutex.Unlock()

	e.finishTime = time.Now()

	e.data["token"] = e.stats.MixPanelToken
	e.data["total_time_s"] = e.finishTime.Sub(e.startTime).Seconds()

	for k, v := range e.stats.globalData {
		e.data[k] = v
	}

	for k, start := range e.subTaskStart {
		if finish, ok := e.subTaskFinish[k]; ok {
			e.data[k+"_time_s"] = finish.Sub(start).Seconds()
		}
		// TODO: log something here???
	}

	if e.Client == nil {
		e.Client = e.stats.Client
	}

	mp := &mixpanel{}
	mp.Client = e.Client
	mp.Event = e.eventName
	mp.Properties = e.data
	mp.Verbose = e.stats.Verbose
	return mp.send()
}

// Add will add data to be sent to mixpanel.
func (e *Event) Add(name string, value interface{}) {
	e.mutex.Lock()
	defer e.mutex.Unlock()
	if e.data == nil {
		e.data = make(map[string]interface{})
	}

	e.data[name] = value
}
