// 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
// +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 }
