// Copyright 2021 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

// zap provides an implementation of zapcore.Core for events.
// To use globally:
//
//	zap.ReplaceGlobals(zap.New(NewCore(exporter)))
//
// If you call elogging.SetExporter, then you can pass nil
// for the exporter above and it will use the global one.
package zap

import (
	"context"
	"fmt"
	"math"
	"reflect"
	"time"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"golang.org/x/exp/event"
	"golang.org/x/exp/event/severity"
)

type core struct {
	ev     *event.Event // cloned but never delivered
	labels []event.Label
}

var _ zapcore.Core = (*core)(nil)

func NewCore(ctx context.Context) zapcore.Core {
	return &core{ev: event.New(ctx, event.LogKind)}
}

func (c *core) Enabled(level zapcore.Level) bool {
	return true
}

func (c *core) With(fields []zapcore.Field) zapcore.Core {
	c2 := *c
	if len(fields) > 0 {
		c2.labels = make([]event.Label, len(c.labels), len(c.labels)+len(fields))
		copy(c2.labels, c.labels)
		for _, f := range fields {
			c2.labels = append(c2.labels, newLabel(f))
		}
	}
	return &c2
}

func (c *core) Write(e zapcore.Entry, fs []zapcore.Field) error {
	if c.ev == nil {
		return nil
	}
	ev := c.ev.Clone()
	if ev == nil {
		return nil
	}
	ev.At = e.Time
	// TODO: Add labels more efficiently: compare cap(ev.Labels) to the total number to add,
	// and allocate a []Label once.
	ev.Labels = append(ev.Labels, c.labels...)
	ev.Labels = append(ev.Labels, convertLevel(e.Level).Label())
	ev.Labels = append(ev.Labels, event.String("name", e.LoggerName))
	if e.Stack != "" {
		ev.Labels = append(ev.Labels, event.String("stack", e.Stack))
	}
	if e.Caller.Defined {
		ev.Labels = append(ev.Labels, event.String("caller", e.Caller.String()))
	}
	for _, f := range fs {
		ev.Labels = append(ev.Labels, newLabel(f))
	}
	ev.Labels = append(ev.Labels, event.String("msg", e.Message))
	ev.Deliver()
	return nil
}

func (c *core) Check(e zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
	return ce.AddCore(e, c)
}

func (c *core) Sync() error { return nil }

func newLabel(f zap.Field) event.Label {
	switch f.Type {
	case zapcore.ArrayMarshalerType, zapcore.ObjectMarshalerType, zapcore.BinaryType, zapcore.ByteStringType,
		zapcore.Complex128Type, zapcore.Complex64Type, zapcore.TimeFullType, zapcore.ReflectType,
		zapcore.ErrorType:
		return event.Value(f.Key, f.Interface)
	case zapcore.DurationType:
		return event.Duration(f.Key, time.Duration(f.Integer))
	case zapcore.Float64Type:
		return event.Float64(f.Key, math.Float64frombits(uint64(f.Integer)))
	case zapcore.Float32Type:
		return event.Float64(f.Key, float64(math.Float32frombits(uint32(f.Integer))))
	case zapcore.BoolType:
		b := false
		if f.Integer != 0 {
			b = true
		}
		return event.Bool(f.Key, b)
	case zapcore.Int64Type:
		return event.Int64(f.Key, f.Integer)
	case zapcore.Int32Type:
		return event.Int64(f.Key, f.Integer)

		//, zapcore.Int16Type, zapcore.Int8Type,
		// 		zapcore.Uint64Type, zapcore.Uint32Type, zapcore.Uint16Type, zapcore.Uint8Type, zapcore.UintptrType:
		//		return (f.Key,uint64(f.Integer))
	case zapcore.StringType:
		return event.String(f.Key, f.String)
	case zapcore.TimeType:
		t := time.Unix(0, f.Integer)
		if f.Interface != nil {
			t = t.In(f.Interface.(*time.Location))
		}
		return event.Value(f.Key, t)
	case zapcore.StringerType:
		return event.String(f.Key, stringerToString(f.Interface))
	case zapcore.NamespaceType:
		// TODO: ???
		return event.Label{}
	case zapcore.SkipType:
		// TODO: avoid creating a label at all in this case.
		return event.Label{}
	default:
		panic(fmt.Sprintf("unknown field type: %v", f))
	}
}

// Adapter from encodeStringer in go.uber.org/zap/zapcore/field.go.
func stringerToString(stringer interface{}) (s string) {
	// Try to capture panics (from nil references or otherwise) when calling
	// the String() method, similar to https://golang.org/src/fmt/print.go#L540
	defer func() {
		if err := recover(); err != nil {
			// If it's a nil pointer, just say "<nil>". The likeliest causes are a
			// Stringer that fails to guard against nil or a nil pointer for a
			// value receiver, and in either case, "<nil>" is a nice result.
			if v := reflect.ValueOf(stringer); v.Kind() == reflect.Ptr && v.IsNil() {
				s = "<nil>"
				return
			}
			s = fmt.Sprintf("PANIC=%v", err)
		}
	}()

	return stringer.(fmt.Stringer).String()
}

func convertLevel(level zapcore.Level) severity.Level {
	switch level {
	case zapcore.DebugLevel:
		return severity.Debug
	case zapcore.InfoLevel:
		return severity.Info
	case zapcore.WarnLevel:
		return severity.Warning
	case zapcore.ErrorLevel:
		return severity.Error
	case zapcore.DPanicLevel:
		return severity.Fatal - 1
	case zapcore.PanicLevel:
		return severity.Fatal + 1
	case zapcore.FatalLevel:
		return severity.Fatal
	default:
		return severity.Trace
	}
}
