package log

import (
	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"
	"gopkg.in/natefinch/lumberjack.v2"
	"io"
	"os"
	"path/filepath"
)

var (
	logger     zerolog.Logger
	wineLogger zerolog.Logger
)

func SetupLogging() {
	// App logs
	path, err := getLogfilePath()
	if err != nil {
		log.Error().Err(err).Str("path", path).Msg("Failed to get log path")
		return
	}

	var mw io.Writer
	l := createLogWriter(path, 10, 3)
	if l != nil {
		mw = io.MultiWriter(zerolog.ConsoleWriter{Out: os.Stdout}, l)
	} else {
		mw = io.MultiWriter(zerolog.ConsoleWriter{Out: os.Stdout})
	}
	logger = zerolog.New(mw).With().Timestamp().Logger()
	SetLevelInfo()

	// Wine logs
	wineLogPath, err := getWineLogfilePath()
	if err != nil {
		Errorf("Failed to get wine log path: %v", err)
		return
	}
	l = createLogWriter(wineLogPath, 25, 1)
	if l != nil {
		mw = io.MultiWriter(zerolog.ConsoleWriter{Out: os.Stdout}, l)
	} else {
		mw = io.MultiWriter(zerolog.ConsoleWriter{Out: os.Stdout})
	}
	wineLogger = zerolog.New(mw).With().Timestamp().Logger()
	wineLogger.Level(zerolog.InfoLevel)
}

func createLogWriter(path string, maxSize int, maxBackups int) io.Writer {
	if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
		log.Error().Err(err).Str("path", path).Msg("Failed to create log path")
		return nil
	}

	return &lumberjack.Logger{
		Filename:   path,
		MaxSize:    maxSize,
		MaxBackups: maxBackups,
	}
}

func SetLevelDebug() {
	logger.Level(zerolog.DebugLevel)
}

func SetLevelInfo() {
	logger.Level(zerolog.InfoLevel)
}

func getLogfilePath() (string, error) {
	dir, err := os.UserConfigDir()
	if err != nil {
		return "", err
	}
	return filepath.Join(dir, "EpochSilicon", "epochsilicon.log"), nil
}

func getWineLogfilePath() (string, error) {
	dir, err := os.UserConfigDir()
	if err != nil {
		return "", err
	}
	return filepath.Join(dir, "EpochSilicon", "epochsilicon.log"), nil
}

func Debug(msg string) {
	logger.Debug().Msg(msg)
}

func Debugf(format string, args ...interface{}) {
	logger.Debug().Msgf(format, args...)
}

func Info(msg string) {
	logger.Info().Msg(msg)
}

func Infof(format string, args ...interface{}) {
	logger.Info().Msgf(format, args...)
}

func Warn(msg string) {
	logger.Warn().Msg(msg)
}

func Warnf(format string, args ...interface{}) {
	logger.Warn().Msgf(format, args...)
}

func Error(msg string) {
	logger.Error().Msg(msg)
}

func Errorf(format string, args ...interface{}) {
	logger.Error().Msgf(format, args...)
}

func Fatal(msg string) {
	logger.Fatal().Msg(msg)
}

func Fatalf(format string, args ...interface{}) {
	logger.Fatal().Msgf(format, args...)
}

func Panic(msg string) {
	logger.Panic().Msg(msg)
}

func Panicf(format string, args ...interface{}) {
	logger.Panic().Msgf(format, args...)
}

func WineLoggerStdout(msg string) {
	wineLogger.Info().Msgf("STDOUT: %s", msg)
}

func WineLoggerStderr(msg string) {
	wineLogger.Info().Msgf("STDERR: %s", msg)
}
