package logger

import (
	"fmt"
	"os"
	"strings"
	"time"
)

func (log *loggerImpl) getLogHeader(logLevel string) string {
	t := time.Now().UTC().Format(timeLayout)
	return fmt.Sprintf("[%s %s %s]", t, logLevel, log.callerIdent)
}

func escapeNewLine(str string) string {
	return strings.ReplaceAll(str, "\n", "\\n")
}

/*******************************DEBUG METHODS*************************************/

func (log *loggerImpl) Debugf(format string, args ...interface{}) {
	hdr := log.getLogHeader(debugLevel)
	mes := fmt.Sprintf(format, args...)
	mes = escapeNewLine(mes)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

func (log *loggerImpl) Debug(args ...interface{}) {
	hdr := log.getLogHeader(debugLevel)
	mes := fmt.Sprint(args...)
	mes = escapeNewLine(mes)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

func (log *loggerImpl) Debugln(args ...interface{}) {
	hdr := log.getLogHeader(debugLevel)
	mes := fmt.Sprintln(args...)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

/*******************************INFO METHODS*************************************/

func (log *loggerImpl) Infof(format string, args ...interface{}) {
	hdr := log.getLogHeader(infoLevel)
	mes := fmt.Sprintf(format, args...)
	mes = escapeNewLine(mes)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

func (log *loggerImpl) Info(args ...interface{}) {
	hdr := log.getLogHeader(infoLevel)
	mes := fmt.Sprint(args...)
	mes = escapeNewLine(mes)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

func (log *loggerImpl) Infoln(args ...interface{}) {
	hdr := log.getLogHeader(infoLevel)
	mes := fmt.Sprintln(args...)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

/*******************************INFO METHODS*************************************/

func (log *loggerImpl) Printf(format string, args ...interface{}) {
	hdr := log.getLogHeader(infoLevel)
	mes := fmt.Sprintf(format, args...)
	mes = escapeNewLine(mes)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

func (log *loggerImpl) Print(args ...interface{}) {
	hdr := log.getLogHeader(infoLevel)
	mes := fmt.Sprint(args...)
	mes = escapeNewLine(mes)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

func (log *loggerImpl) Println(args ...interface{}) {
	hdr := log.getLogHeader(infoLevel)
	mes := fmt.Sprintln(args...)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

/*******************************WARN METHODS*************************************/

func (log *loggerImpl) Warnf(format string, args ...interface{}) {
	hdr := log.getLogHeader(warnLevel)
	mes := fmt.Sprintf(format, args...)
	mes = escapeNewLine(mes)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

func (log *loggerImpl) Warn(args ...interface{}) {
	hdr := log.getLogHeader(warnLevel)
	mes := fmt.Sprint(args...)
	mes = escapeNewLine(mes)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

func (log *loggerImpl) Warnln(args ...interface{}) {
	hdr := log.getLogHeader(warnLevel)
	mes := fmt.Sprintln(args...)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

/*******************************ERROR METHODS*************************************/

func (log *loggerImpl) Errorf(format string, args ...interface{}) {
	hdr := log.getLogHeader(errLevel)
	mes := fmt.Sprintf(format, args...)
	mes = escapeNewLine(mes)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

func (log *loggerImpl) Error(args ...interface{}) {
	hdr := log.getLogHeader(errLevel)
	mes := fmt.Sprint(args...)
	mes = escapeNewLine(mes)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

func (log *loggerImpl) Errorln(args ...interface{}) {
	hdr := log.getLogHeader(errLevel)
	mes := fmt.Sprintln(args...)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
}

/*******************************FATAL METHODS*************************************/

func (log *loggerImpl) Fatalf(format string, args ...interface{}) {
	hdr := log.getLogHeader(fatalLevel)
	mes := fmt.Sprintf(format, args...)
	mes = escapeNewLine(mes)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
	os.Exit(1)
}

func (log *loggerImpl) Fatal(args ...interface{}) {
	hdr := log.getLogHeader(fatalLevel)
	mes := fmt.Sprint(args...)
	mes = escapeNewLine(mes)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
	os.Exit(1)
}

func (log *loggerImpl) Fatalln(args ...interface{}) {
	hdr := log.getLogHeader(fatalLevel)
	mes := fmt.Sprintln(args...)
	fmt.Fprintf(os.Stderr, "%s: %s\n", hdr, mes)
	os.Exit(1)
}
