// Helper functions to analyze the slices of Timestamps that are
// provided with code.justin.tv/release/trace/api.Call.

package api

import (
	"time"

	"code.justin.tv/release/trace/events"
)

// Time returns the timestamp of an Event in UTC
func Time(ev *events.Event) time.Time {
	var t int64
	if ev != nil {
		t = ev.Time
	}
	return time.Unix(0, t).UTC()
}

// ClientDuration returns the total amount of time a call took
// according to the client. Returns 0 if insufficient data is
// available from the client.
func ClientDuration(c *Call) time.Duration {
	if ts := c.GetClientTimestamps(); len(ts) > 1 {
		return time.Duration(ts[len(ts)-1].Time - ts[0].Time)
	}
	return time.Duration(0)
}

// ServiceDuration returns the total amount of time a call took
// according to the service. Returns 0 if insufficient data is
// available from the service.
func ServiceDuration(c *Call) time.Duration {
	if ts := c.GetServiceTimestamps(); len(ts) > 1 {
		return time.Duration(ts[len(ts)-1].Time - ts[0].Time)
	}
	return time.Duration(0)
}

// NetworkDuration returns the total amount of time a call spent being
// sent over the network, based on the difference observed in the
// client and service durations. Returns 0 if insufficient data is
// available, and promises to never return negative values.
func NetworkDuration(c *Call) time.Duration {
	if delta := ClientDuration(c) - ServiceDuration(c); delta > 0 {
		return delta
	}
	return 0
}

// first returns the first time of the Timestamps in the slice.
func first(ts []*Timestamp) time.Time {
	return time.Unix(0, ts[0].Time).UTC()
}

// ClientStart returns the timestamp of the first event logged by the
// client in this call. It returns a zero Time if the client has not
// provided data. The Time returned is in UTC.
func ClientStart(c *Call) time.Time {
	if ts := c.GetClientTimestamps(); ts != nil {
		return first(ts)
	}
	return time.Time{}
}

// ServiceStart returns the timestamp of the first event logged by the
// service  in this call. It returns a zero Time if the service has not
// provided data. The time returned is in UTC.
func ServiceStart(c *Call) time.Time {
	if ts := c.GetServiceTimestamps(); ts != nil {
		return first(ts)
	}
	return time.Time{}
}

// last returns the last time of the Timestamps in the slice.
func last(ts []*Timestamp) time.Time {
	return time.Unix(0, ts[len(ts)-1].Time).UTC()
}

// ClientEnd returns the timestamp of the last event logged by the
// client in this call. It returns a zero Time if the client has not
// provided data. The time returned is in UTC.
func ClientEnd(c *Call) time.Time {
	if ts := c.GetClientTimestamps(); ts != nil {
		return last(ts)
	}
	return time.Time{}
}

// ServiceEnd returns the timestamp of the last event logged by the
// service  in this call. It returns a zero Time if the service has not
// provided data. The time returned is in UTC.
func ServiceEnd(c *Call) time.Time {
	if ts := c.GetServiceTimestamps(); ts != nil {
		return last(ts)
	}
	return time.Time{}
}
