package opentracing

import 

type contextKey struct{}

var activeSpanKey = contextKey{}

// ContextWithSpan returns a new `context.Context` that holds a reference to
// the span. If span is nil, a new context without an active span is returned.
func ( context.Context,  Span) context.Context {
	if  != nil {
		if ,  := .Tracer().(TracerContextWithSpanExtension);  {
			 = .ContextWithSpanHook(, )
		}
	}
	return context.WithValue(, activeSpanKey, )
}

// SpanFromContext returns the `Span` previously associated with `ctx`, or
// `nil` if no such `Span` could be found.
//
// NOTE: context.Context != SpanContext: the former is Go's intra-process
// context propagation mechanism, and the latter houses OpenTracing's per-Span
// identity and baggage information.
func ( context.Context) Span {
	 := .Value(activeSpanKey)
	if ,  := .(Span);  {
		return 
	}
	return nil
}

// StartSpanFromContext starts and returns a Span with `operationName`, using
// any Span found within `ctx` as a ChildOfRef. If no such parent could be
// found, StartSpanFromContext creates a root (parentless) Span.
//
// The second return value is a context.Context object built around the
// returned Span.
//
// Example usage:
//
//    SomeFunction(ctx context.Context, ...) {
//        sp, ctx := opentracing.StartSpanFromContext(ctx, "SomeFunction")
//        defer sp.Finish()
//        ...
//    }
func ( context.Context,  string,  ...StartSpanOption) (Span, context.Context) {
	return StartSpanFromContextWithTracer(, GlobalTracer(), , ...)
}

// StartSpanFromContextWithTracer starts and returns a span with `operationName`
// using  a span found within the context as a ChildOfRef. If that doesn't exist
// it creates a root span. It also returns a context.Context object built
// around the returned span.
//
// It's behavior is identical to StartSpanFromContext except that it takes an explicit
// tracer as opposed to using the global tracer.
func ( context.Context,  Tracer,  string,  ...StartSpanOption) (Span, context.Context) {
	if  := SpanFromContext();  != nil {
		 = append(, ChildOf(.Context()))
	}
	 := .StartSpan(, ...)
	return , ContextWithSpan(, )
}