// 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.

package event

import (
	"context"
	"fmt"
	"sync"
)

const (
	MetricKey      = interfaceKey("metric")
	MetricVal      = "metricValue"
	DurationMetric = interfaceKey("durationMetric")
)

type Kind int

const (
	unknownKind = Kind(iota)

	LogKind
	MetricKind
	StartKind
	EndKind

	dynamicKindStart
)

type (
	valueKey     string
	interfaceKey string
)

var (
	dynamicKindMu    sync.Mutex
	nextDynamicKind  = dynamicKindStart
	dynamicKindNames map[Kind]string
)

func NewKind(name string) Kind {
	dynamicKindMu.Lock()
	defer dynamicKindMu.Unlock()
	for _, n := range dynamicKindNames {
		if n == name {
			panic(fmt.Errorf("kind %s is already registered", name))
		}
	}
	k := nextDynamicKind
	nextDynamicKind++
	dynamicKindNames[k] = name
	return k
}

func (k Kind) String() string {
	switch k {
	case unknownKind:
		return "unknown"
	case LogKind:
		return "log"
	case MetricKind:
		return "metric"
	case StartKind:
		return "start"
	case EndKind:
		return "end"
	default:
		dynamicKindMu.Lock()
		defer dynamicKindMu.Unlock()
		name, ok := dynamicKindNames[k]
		if !ok {
			return fmt.Sprintf("?unknownKind:%d?", k)
		}
		return name
	}
}

func Log(ctx context.Context, msg string, labels ...Label) {
	ev := New(ctx, LogKind)
	if ev != nil {
		ev.Labels = append(ev.Labels, labels...)
		ev.Labels = append(ev.Labels, String("msg", msg))
		ev.Deliver()
	}
}

func Logf(ctx context.Context, msg string, args ...interface{}) {
	ev := New(ctx, LogKind)
	if ev != nil {
		ev.Labels = append(ev.Labels, String("msg", fmt.Sprintf(msg, args...)))
		ev.Deliver()
	}
}

func Error(ctx context.Context, msg string, err error, labels ...Label) {
	ev := New(ctx, LogKind)
	if ev != nil {
		ev.Labels = append(ev.Labels, labels...)
		ev.Labels = append(ev.Labels, String("msg", msg), Value("error", err))
		ev.Deliver()
	}
}

func Annotate(ctx context.Context, labels ...Label) {
	ev := New(ctx, 0)
	if ev != nil {
		ev.Labels = append(ev.Labels, labels...)
		ev.Deliver()
	}
}

func Start(ctx context.Context, name string, labels ...Label) context.Context {
	ev := New(ctx, StartKind)
	if ev != nil {
		ev.Labels = append(ev.Labels, String("name", name))
		ev.Labels = append(ev.Labels, labels...)
		ev.Trace()
		ctx = ev.Deliver()
	}
	return ctx
}

func End(ctx context.Context, labels ...Label) {
	ev := New(ctx, EndKind)
	if ev != nil {
		ev.Labels = append(ev.Labels, labels...)
		ev.prepare()
		// this was an end event, do we need to send a duration?
		if v, ok := DurationMetric.Find(ev); ok {
			//TODO: do we want the rest of the values from the end event?
			v.(*DurationDistribution).Record(ctx, ev.At.Sub(ev.target.startTime))
		}
		ev.Deliver()
	}
}

func (k interfaceKey) Of(v interface{}) Label {
	return Value(string(k), v)
}

func (k interfaceKey) Find(ev *Event) (interface{}, bool) {
	v, ok := lookupValue(string(k), ev.Labels)
	if !ok {
		return nil, false
	}
	return v.Interface(), true

}

func lookupValue(name string, labels []Label) (Label, bool) {
	for i := len(labels) - 1; i >= 0; i-- {
		if labels[i].Name == name {
			return labels[i], true
		}
	}
	return Label{}, false
}
