// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build !disable_events

package event

import (
	"context"
	"sync"
	"sync/atomic"
	"time"
	"unsafe"
)

// Exporter synchronizes the delivery of events to handlers.
type Exporter struct {
	lastEvent uint64 // accessed using atomic, must be 64 bit aligned
	opts      ExporterOptions

	mu      sync.Mutex
	handler Handler
	sources sources
}

// target is a bound exporter.
// Normally you get a target by looking in the context using To.
type target struct {
	exporter  *Exporter
	parent    uint64
	startTime time.Time // for trace latency
}

type ExporterOptions struct {
	// If non-nil, sets zero Event.At on delivery.
	Now func() time.Time

	// Disable some event types, for better performance.
	DisableLogging     bool
	DisableTracing     bool
	DisableAnnotations bool
	DisableMetrics     bool

	// Enable automatically setting the event Namespace to the calling package's
	// import path.
	EnableNamespaces bool
}

// contextKeyType is used as the key for storing a contextValue on the context.
type contextKeyType struct{}

var contextKey interface{} = contextKeyType{}

var (
	defaultTarget unsafe.Pointer
)

// NewExporter creates an Exporter using the supplied handler and options.
// Event delivery is serialized to enable safe atomic handling.
func NewExporter(handler Handler, opts *ExporterOptions) *Exporter {
	if handler == nil {
		panic("handler must not be nil")
	}
	e := &Exporter{
		handler: handler,
		sources: newCallers(),
	}
	if opts != nil {
		e.opts = *opts
	}
	if e.opts.Now == nil {
		e.opts.Now = time.Now
	}
	return e
}

func setDefaultExporter(e *Exporter) {
	atomic.StorePointer(&defaultTarget, unsafe.Pointer(&target{exporter: e}))
}

func getDefaultTarget() *target {
	return (*target)(atomic.LoadPointer(&defaultTarget))
}

func newContext(ctx context.Context, exporter *Exporter, parent uint64, start time.Time) context.Context {
	var t *target
	if exporter != nil {
		t = &target{exporter: exporter, parent: parent, startTime: start}
	}
	return context.WithValue(ctx, contextKey, t)
}

// prepare events before delivering to the underlying handler.
// it is safe to call this more than once (trace events have to call it early)
// If the event does not have a timestamp, and the exporter has a Now function
// then the timestamp will be updated.
// If automatic namespaces are enabled and the event doesn't have a namespace,
// one based on the caller's import path will be provided.
func (ev *Event) prepare() {
	e := ev.target.exporter
	if ev.ID == 0 {
		ev.ID = atomic.AddUint64(&e.lastEvent, 1)
	}
	if e.opts.Now != nil && ev.At.IsZero() {
		ev.At = e.opts.Now()
	}
	if e.opts.EnableNamespaces && ev.Source.Space == "" {
		ev.Source = e.sources.scanStack()
	}
}

func (e *Exporter) loggingEnabled() bool     { return !e.opts.DisableLogging }
func (e *Exporter) annotationsEnabled() bool { return !e.opts.DisableAnnotations }
func (e *Exporter) tracingEnabled() bool     { return !e.opts.DisableTracing }
func (e *Exporter) metricsEnabled() bool     { return !e.opts.DisableMetrics }
