package logger

import (
	"path"
	"strconv"

	//"github.com/natefinch/lumberjack"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"time"
)

var (
	fileLogCoreMap map[string]*zap.Logger
)

type fileDriver struct {
	level  int
	logger *zap.Logger
}

func NewFileDriver(config file, level int) (driver, error) {
	var logCore *zap.Logger
	if fileLogCoreMap == nil {
		fileLogCoreMap = make(map[string]*zap.Logger)
	}

	mKey := config.Filename+strconv.Itoa(config.MaxAge)
	logCore = fileLogCoreMap[mKey]
	if logCore == nil {

		//lumberjackLogger := &lumberjack.Logger{
		//	Filename:   config.Filename,
		//	MaxSize:    config.MaxSize,
		//	MaxAge:     config.MaxAge,
		//	MaxBackups: config.MaxBackups,
		//	Compress:   config.Compress,
		//}
		processDir, err := GetCurrentPath("")
		if err != nil {
			return nil, err
		}
		age := time.Hour * 24 * time.Duration(config.MaxAge)
		hook, err := rotatelogs.New(
			path.Join(processDir, config.Filename+".%Y%m%d"),
			rotatelogs.WithLinkName(config.Filename),
			rotatelogs.WithMaxAge(age),
			rotatelogs.WithRotationTime(time.Hour*24),
		)

		if err != nil {
			return nil, err
		}
		writeSync := zapcore.AddSync(hook)
		coreEncoder := zap.NewProductionEncoderConfig()
		coreEncoder.EncodeLevel = zapcore.CapitalLevelEncoder
		encoder := zapcore.NewJSONEncoder(coreEncoder)
		core := zapcore.NewCore(encoder, writeSync, zap.DebugLevel)
		logCore = zap.New(core)
		fileLogCoreMap[mKey] = logCore
	}
	return &fileDriver{level, logCore}, nil
}

func (f *fileDriver) Record(message message) {
	if (message.Level == debugLevel || message.Level == DebugLevel) && f.level == debugLevelInt {
		f.logger.Debug(message.Content,
			zap.String("Extra", message.Extra),
			zap.Int("Pid", message.Pid),
			zap.String("Module", message.Module),
			zap.String("Operator", message.Operator),
			zap.String("Caller", message.Caller),
			zap.String("Date", message.Date),
			zap.String("Time", message.Time))
	} else if (message.Level == infoLevel || message.Level == InfoLevel) && f.level <= infoLevelInt {
		f.logger.Info(message.Content,
			zap.String("Extra", message.Extra),
			zap.Int("Pid", message.Pid),
			zap.String("Module", message.Module),
			zap.String("Operator", message.Operator),
			zap.String("Caller", message.Caller),
			zap.String("Date", message.Date),
			zap.String("Time", message.Time))
	} else if (message.Level == warnLevel || message.Level == WarnLevel) && f.level <= warnLevelInt {
		f.logger.Warn(message.Content,
			zap.String("Extra", message.Extra),
			zap.Int("Pid", message.Pid),
			zap.String("Module", message.Module),
			zap.String("Operator", message.Operator),
			zap.String("Caller", message.Caller),
			zap.String("Date", message.Date),
			zap.String("Time", message.Time))
	} else if (message.Level == errorLevel || message.Level == ErrorLevel) && f.level <= errorLevelInt {
		f.logger.Error(message.Content,
			zap.String("Extra", message.Extra),
			zap.Int("Pid", message.Pid),
			zap.String("Module", message.Module),
			zap.String("Operator", message.Operator),
			zap.String("Caller", message.Caller),
			zap.String("Date", message.Date),
			zap.String("Time", message.Time))
	} else if (message.Level == fatalLevel || message.Level == FatalLevel) && f.level <= fatalLevelInt {
		f.logger.Fatal(message.Content,
			zap.String("Extra", message.Extra),
			zap.Int("Pid", message.Pid),
			zap.String("Module", message.Module),
			zap.String("Operator", message.Operator),
			zap.String("Caller", message.Caller),
			zap.String("Date", message.Date),
			zap.String("Time", message.Time))
	}
}
