package kernel

import (
	"io"
	"log"
	"os"
)

func init() {
	log.SetFlags(logFlags)

	writer = os.NewFile(0, os.DevNull)

	SetLogLevel(LevelError)
}

const (
	logFlags = log.Llongfile | log.Lmicroseconds | log.LUTC | log.Lmsgprefix
)

var (
	writer  io.Writer
	loggers = []*log.Logger{
		log.New(os.Stdout, "[ERROR] ", logFlags),
		log.New(os.Stdout, "[INFO] ", logFlags),
		log.New(os.Stdout, "[TRACE] ", logFlags),
	}

	ErrorLog Logger = loggers[LevelError]
	InfoLog  Logger = loggers[LevelInfo]
	TraceLog Logger = loggers[LevelTrace]
)

type LogLevel int

var currentLogLevel LogLevel

const (
	LevelError LogLevel = iota
	LevelInfo
	LevelTrace
)

func FatalErr(err error) {
	ErrorLog.Printf("fatal error occurred: %v", err)
	os.Exit(1)
}

func ToLogLevel(ll string) LogLevel {
	switch ll {
	case "ERROR":
		return LevelError
	case "INFO":
		return LevelInfo
	case "TRACE":
		return LevelTrace
	}

	return LevelTrace
}

type Logger interface {
	Println(...any)
	Printf(string, ...any)
}

func SetLogLevel(ll LogLevel) {
	currentLogLevel = ll
	for i := 0; i < len(loggers); i++ {
		target := writer

		if int(ll) >= i {
			target = os.Stdout
		}

		loggers[i].SetOutput(target)

	}
}
