// Copyright 2019 The Fuchsia 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 logger

import (
	"bytes"
	"context"
	"fmt"
	"os"
	"reflect"
	"regexp"
	"sort"
	"testing"

	"go.fuchsia.dev/fuchsia/tools/lib/color"
)

func TestWithContext(t *testing.T) {
	logger := NewLogger(DebugLevel, color.NewColor(color.ColorAuto), os.Stdout, os.Stderr, "")
	ctx := context.Background()
	if v, ok := ctx.Value(globalLoggerKeyType{}).(*Logger); ok || v != nil {
		t.Fatalf("Default context should not have globalLoggerKeyType. Expected: \nnil\n but got: \n%+v ", v)
	}
	ctx = WithLogger(ctx, logger)
	if v, ok := ctx.Value(globalLoggerKeyType{}).(*Logger); !ok || v == nil {
		t.Fatalf("Updated context should have globalLoggerKeyType, but got nil")
	}
}

func TestNewLogger(t *testing.T) {
	prefix := "testprefix "

	logger := NewLogger(InfoLevel, color.NewColor(color.ColorAuto), nil, nil, prefix)
	logFlags, errFlags := logger.goLogger.Flags(), logger.goErrorLogger.Flags()

	correctFlags := (Ldate | Lmicroseconds)

	if logFlags != correctFlags || errFlags != correctFlags {
		t.Fatalf("New loggers should have the proper flags set for both standard and error logging. Expected: \n%+v and %+v\n but got: \n%+v and %+v", correctFlags, correctFlags, logFlags, errFlags)
	}

	logPrefix := logger.prefix
	if logPrefix != prefix {
		t.Fatalf("New loggers should use the specified prefix on creation. Expected: \n%+v\n but got: \n%+v", prefix, logPrefix)
	}
}

func TestNewLoggerSetFlags(t *testing.T) {
	flags := Ldate | Lshortfile
	logger := NewLogger(InfoLevel, color.NewColor(color.ColorAuto), nil, nil, "")
	logger.SetFlags(flags)
	logFlags, errFlags := logger.goLogger.Flags(), logger.goErrorLogger.Flags()

	if logFlags != flags || errFlags != flags {
		t.Fatalf("Loggers should have the flags passed into `SetFlags`. Expected: \n%+v and %+v\n but got: \n%+v and %+v", flags, flags, logFlags, errFlags)
	}
}

func TestLogLevel(t *testing.T) {
	level := InfoLevel
	if level.String() != "info" {
		t.Errorf("InfoLevel.String() should return %q, got %q", "info", level.String())
	}

	level.Set("debug")
	if level != DebugLevel {
		t.Errorf("LogLevel.Set() should change the level's value, but value is still %q", level.String())
	}
}

func TestCallDepth(t *testing.T) {
	prefix := "cdprefix "
	infoLog, errLog := "Info log", "Error log"
	outBuffer, errBuffer := new(bytes.Buffer), new(bytes.Buffer)
	logger := NewLogger(DebugLevel, color.NewColor(color.ColorAuto), outBuffer, errBuffer, prefix)
	logger.SetFlags(Ldate | Lshortfile)

	logger.Infof(infoLog)
	logger.Errorf(errLog)

	outBytes, errBytes := outBuffer.Bytes(), errBuffer.Bytes()

	matched, err := regexp.Match(
		fmt.Sprintf(`\d{4}\/\d{2}\/\d{2} logger_test.go:\d+: %s%s`, prefix, infoLog),
		outBytes)
	if err != nil || !matched {
		t.Fatalf("Stdout output was not as expected. Got: %s", outBytes)
	}
	matched, err = regexp.Match(
		fmt.Sprintf(`\d{4}\/\d{2}\/\d{2} logger_test.go:\d+: %s%s%s`, prefix, regexp.QuoteMeta(logger.color.Red("ERROR: ")), errLog),
		errBytes)
	if err != nil || !matched {
		t.Fatalf("Stderr output was not as expected. Got: %s", errBytes)
	}
}

type counterPrefixer struct {
	counter int
}

func (p *counterPrefixer) String() string {
	p.counter++
	return fmt.Sprintf("%d ", p.counter)
}

func TestCustomPrefix(t *testing.T) {
	infoLog, errLog := "Info log", "Error log"
	outBuffer, errBuffer := new(bytes.Buffer), new(bytes.Buffer)

	logger := NewLogger(DebugLevel, color.NewColor(color.ColorAuto), outBuffer, errBuffer, &counterPrefixer{})
	logger.SetFlags(Ldate | Lshortfile)

	logger.Infof(infoLog)
	logger.Errorf(errLog)

	outBytes, errBytes := outBuffer.Bytes(), errBuffer.Bytes()

	matched, err := regexp.Match(
		fmt.Sprintf(`\d{4}\/\d{2}\/\d{2} logger_test.go:\d+: 1 %s`, infoLog),
		outBytes)
	if err != nil || !matched {
		t.Fatalf("Stdout output was not as expected. Got: %s", outBytes)
	}
	matched, err = regexp.Match(
		fmt.Sprintf(`\d{4}\/\d{2}\/\d{2} logger_test.go:\d+: 2 %s%s`, regexp.QuoteMeta(logger.color.Red("ERROR: ")), errLog),
		errBytes)
	if err != nil || !matched {
		t.Fatalf("Stderr output was not as expected. Got: %s", errBytes)
	}
}

func TestAllLevels(t *testing.T) {
	allLevels := AllLevels()

	if len(allLevels) != len(levelToName) {
		t.Fatalf("len(allLevels) = %d, want %d", len(allLevels), len(levelToName))
	}

	levelToNameViaAllLevels := make(map[LogLevel]string)

	for _, level := range allLevels {
		levelToNameViaAllLevels[level] = level.String()
	}

	if !reflect.DeepEqual(levelToNameViaAllLevels, levelToName) {
		t.Fatalf("levelToNameViaAllLevels = %#v, want %#v", levelToNameViaAllLevels, levelToName)
	}

	if !sort.SliceIsSorted(allLevels, func(i, j int) bool { return allLevels[i] < allLevels[j] }) {
		t.Fatalf("expected allLevels to be sorted; allLevels = %#v", allLevels)
	}
}
