// Copyright 2020 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 stdlib_test

import (
	"context"
	"fmt"
	"io"
	"log"
	"testing"

	"golang.org/x/exp/event/eventtest"
)

var (
	baseline = eventtest.Hooks{
		AStart: func(ctx context.Context, a int) context.Context { return ctx },
		AEnd:   func(ctx context.Context) {},
		BStart: func(ctx context.Context, b string) context.Context { return ctx },
		BEnd:   func(ctx context.Context) {},
	}

	stdlibLog = eventtest.Hooks{
		AStart: func(ctx context.Context, a int) context.Context {
			logCtx(ctx).Printf(eventtest.A.Msgf, a)
			return ctx
		},
		AEnd: func(ctx context.Context) {},
		BStart: func(ctx context.Context, b string) context.Context {
			logCtx(ctx).Printf(eventtest.B.Msgf, b)
			return ctx
		},
		BEnd: func(ctx context.Context) {},
	}

	stdlibPrintf = eventtest.Hooks{
		AStart: func(ctx context.Context, a int) context.Context {
			ctxPrintf(ctx, eventtest.A.Msgf, a)
			return ctx
		},
		AEnd: func(ctx context.Context) {},
		BStart: func(ctx context.Context, b string) context.Context {
			ctxPrintf(ctx, eventtest.B.Msgf, b)
			return ctx
		},
		BEnd: func(ctx context.Context) {},
	}
)

func BenchmarkBaseline(b *testing.B) {
	eventtest.RunBenchmark(b, context.Background(), eventtest.Hooks{
		AStart: func(ctx context.Context, a int) context.Context { return ctx },
		AEnd:   func(ctx context.Context) {},
		BStart: func(ctx context.Context, b string) context.Context { return ctx },
		BEnd:   func(ctx context.Context) {},
	})
}

type stdlibLogKey struct{}

func logCtx(ctx context.Context) *log.Logger {
	return ctx.Value(stdlibLogKey{}).(*log.Logger)
}

func stdlibLogger(w io.Writer) context.Context {
	logger := log.New(w, "", log.LstdFlags)
	return context.WithValue(context.Background(), stdlibLogKey{}, logger)
}

func stdlibLoggerNoTime(w io.Writer) context.Context {
	// there is no way to fixup the time, so we have to suppress it
	logger := log.New(w, "", 0)
	return context.WithValue(context.Background(), stdlibLogKey{}, logger)
}

type writerKey struct{}

func ctxPrintf(ctx context.Context, msg string, args ...interface{}) {
	ctx.Value(writerKey{}).(func(string, ...interface{}))(msg, args...)
}

func stdlibWriter(w io.Writer) context.Context {
	now := eventtest.ExporterOptions().Now
	return context.WithValue(context.Background(), writerKey{},
		func(msg string, args ...interface{}) {
			fmt.Fprintf(w, "time=%q level=info msg=%q\n",
				now().Format(eventtest.TimeFormat),
				fmt.Sprintf(msg, args...))
		},
	)
}

func BenchmarkStdlibLogfDiscard(b *testing.B) {
	eventtest.RunBenchmark(b, stdlibLogger(io.Discard), stdlibLog)
}

func BenchmarkStdlibPrintfDiscard(b *testing.B) {
	eventtest.RunBenchmark(b, stdlibWriter(io.Discard), stdlibPrintf)
}

func TestLogStdlib(t *testing.T) {
	eventtest.TestBenchmark(t, stdlibLoggerNoTime, stdlibLog, `
a where A=0
b where B="A value"
a where A=1
b where B="Some other value"
a where A=22
b where B="Some other value"
a where A=333
b where B=" "
a where A=4444
b where B="prime count of values"
a where A=55555
b where B="V"
a where A=666666
b where B="A value"
a where A=7777777
b where B="A value"
`)
}

func TestLogPrintf(t *testing.T) {
	eventtest.TestBenchmark(t, stdlibWriter, stdlibPrintf, eventtest.LogfOutput)
}
