package main

import (
	"fmt"
	"sync"
	"time"
)

type LogLevel uint8

const (
	DebugLevel = iota
	TraceLevel
	InfoLevel
	WarningLevel
	ErrorLevel
)

var (
	levels = map[LogLevel]string{
		DebugLevel:   "Debug",
		TraceLevel:   "Trace",
		InfoLevel:    "Info",
		WarningLevel: "Warning",
		ErrorLevel:   "Error",
	}
)

var Logger *SystemLogger = newSystemLogger()

type SystemLogger struct {
	locker *sync.Mutex
}

//Create the default console logger.
func newSystemLogger() *SystemLogger {
	l := new(SystemLogger)
	l.locker = new(sync.Mutex)
	return l
}

//Write the log by different level.
func (l *SystemLogger) log(level LogLevel, msg string) {
	defer func() {
		var p = any(recover())
		if p != nil {
			l.locker.Unlock()
		}
	}()
	now := time.Now()
	timeStr := now.Format("2006-01-02 15:04:05.000000000")
	l.locker.Lock()
	fmt.Println(levels[level] + "- [" + timeStr + "] " + msg)
	l.locker.Unlock()
}

// Debug Write the debug log.
func (l *SystemLogger) Debug(msg string) {
	l.log(DebugLevel, msg)
}

// Trace Write the trace log.
func (l *SystemLogger) Trace(msg string) {
	l.log(TraceLevel, msg)
}

// Info Write the info log.
func (l *SystemLogger) Info(msg string) {
	l.log(InfoLevel, msg)
}

// Warning Write the warning log.
func (l *SystemLogger) Warning(msg string) {
	l.log(WarningLevel, msg)
}

//Write the error log.
func (l *SystemLogger) Error(msg string) {
	l.log(ErrorLevel, msg)
}
