// Package log provides a uniform method of logging for
// all go projects at plusserver
package log

import (
	"fmt"
	"os"
	"time"

	"github.com/fatih/color"
)

// LogLevel is our custom type that represents the different log levels
type LogLevel int

// Log levels that can be assigned to the WriteLog function
const (
	ERROR LogLevel = iota
	WARNING
	INFO
	DEBUG
)

// This implements the String representation for our custom type logLevel
func (l LogLevel) String() string {
	switch l {
	case WARNING:
		return "WARNING"
	case ERROR:
		return "ERROR"
	case INFO:
		return "INFO"
	default:
		return "DEBUG"
	}
}

// colorOutput colors the output of a given message according to logLevel
func colorOutput(message string, logLevel LogLevel) {
	switch logLevel {
	case WARNING:
		color.Yellow(message)
	case ERROR:
		color.Red(message)
	case DEBUG:
		color.HiBlack(message)
	default:
		color.Green(message)
	}
}

func parseLogLevel(s string) LogLevel {
	switch s {
	case "DEBUG":
		return DEBUG
	case "INFO":
		return INFO
	case "WARNING":
		return WARNING
	default:
		return ERROR
	}
}

// Print writes the given text to the console and formats it properly.
// If no level is not provided or is unknown it will treat it as "INFO".
//
// Use the constants provided by this package for the available levels.
func Print(printLevel LogLevel, message ...any) {
	// log level set by environment variable
	var envLogLevel LogLevel
	if l := os.Getenv("LOGLEVEL"); l != "" {
		envLogLevel = parseLogLevel(l)
	}

	// don't do anything if the requested print level is lower than the run level
	if printLevel > envLogLevel {
		return
	}

	// get a timestamp for the log message
	timeStamp := time.Now().Format("[2006-01-02 15:04:05]")

	// assemble the log message
	logMessage := fmt.Sprintf("%s [%s]", timeStamp, printLevel)
	for i := range message {
		logMessage += " "
		logMessage += fmt.Sprintf("%v", message[i])
	}
	colorOutput(logMessage, printLevel)
}

// PrintInfo is a Wrapper for Print(INFO, message)
func PrintInfo(message ...any) {
	Print(INFO, message...)
}

// PrintWarning is a Wrapper for Print(WARNING, message)
func PrintWarning(message ...any) {
	Print(WARNING, message...)
}

// PrintError is a Wrapper for Print(ERROR, message)
func PrintError(message ...any) {
	Print(ERROR, message...)
}

// PrintDebug is a Wrapper for Print(DEBUG, message)
func PrintDebug(message ...any) {
	Print(DEBUG, message...)
}