package xray

import "context"

type contextkeytype int

var contextkey = new(contextkeytype)

func getSegment(ctx context.Context) *segment {
	if seg, ok := ctx.Value(contextkey).(*segment); ok {
		return seg
	}
	return nil
}

// TraceID returns the canonical ID of the cross-service trace and
// can be used in XRay's UI to uniquely identify the code paths executed.
func TraceID(ctx context.Context) string {
	if seg, ok := ctx.Value(contextkey).(*segment); ok {
		return seg.TraceID
	}
	return ""
}

// RequestWasTraced returns true if the context contains an XRay segment
// that was created from an HTTP request that contained a trace header.
// This is useful to ensure that a service is only called from XRay traced
// services.
func RequestWasTraced(ctx context.Context) bool {
	for seg := getSegment(ctx); seg != nil; seg = seg.parent {
		if seg.requestWasTraced {
			return true
		}
	}
	return false
}

// DetachContext returns a new context with the existing segment.
// This is useful for creating background tasks which won't be cancelled
// when a request completes.
func DetachContext(ctx context.Context) context.Context {
	return context.WithValue(context.Background(), contextkey, getSegment(ctx))
}

func AddAnnotation(ctx context.Context, key string, value interface{}) error {
	if seg := getSegment(ctx); seg != nil {
		return seg.addAnnotation(key, value)
	}
	return Error("Unable to retrieve segment")
}

func AddMetadata(ctx context.Context, key string, value interface{}) error {
	if seg := getSegment(ctx); seg != nil {
		return seg.addMetadata(key, value)
	}
	return Error("Unable to retrieve segment")
}
