package icslog

import (
	"fmt"
	"os"
	"path/filepath"

	"gitlab.com/cinnamon/voiceagent/icserror"
	"gitlab.com/cinnamon/voiceagent/icsutil"
)

const (
	ONEMB = 1048576
)

func (l *IcsLog) Printf(level int, sessionID int, format string, a ...interface{}) {
	msg := fmt.Sprintf(format, a...)

	if level >= l.Level {
		//check disk full
		aSpace := icsutil.GetDiskAvailableSpace(filepath.Dir(l.LogFileName))
		if aSpace < uint64(l.conf.Disklimit*ONEMB) {
			//if aSpace < uint64(l.conf.LogConfig.Disklimit*ONEMB) {
			if !l.IsDiskFull {
				msg = fmt.Sprintf("Disk Full! Available Disk Space: %dMB", aSpace/ONEMB)
				l.logger.Output(2, msg)
				if l.LogFile != nil {
					l.LogFile.WriteString(l.buf.String())
				}
				l.buf.Reset()
				l.IsDiskFull = true
			}
			return
		}

		l.M.Lock()

		if l.checkLogRotate() {
			//check log size
			stat, err := os.Stat(l.LogFileName)
			if err != nil {
				msg = fmt.Sprintf("Could not get log file(%s) size", l.LogFileName)
				l.logger.Output(2, msg)
				if l.LogFile != nil {
					l.LogFile.WriteString(l.buf.String())
				}
				l.buf.Reset()

				l.M.Unlock()

				return
			}

			if stat.Size()/ONEMB >= int64(l.logSize) {
				//shift log files
				rotateNum := gIcsLog.getTodayLogFileNum()
				if rotateNum > 0 && rotateNum < gIcsLog.rotateNum {
					gIcsLog.shiftLogFiles(rotateNum)

					l.LogFile.Sync()
					l.LogFile.Close()

					//open new log file
					var oerr error
					//fmt.Println("LOG rotate new log file", l.LogFileName)
					l.LogFile, oerr = os.OpenFile(l.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
					if oerr != nil {
						icserror.ICSERRFileOpen.SetError(oerr)
						icserror.ICSERRFileOpen.PrintWithCaller(1)

						l.M.Unlock()
						return
					}
				} else {
					l.M.Unlock()
					return
				}
			}
		}

		//write log
		if level < LOG_LEVEL_DEBUG2 || level > LOG_LEVEL_FATAL {
			level = LOG_LEVEL_INFO
		}
		var logmsg string
		if sessionID >= 0 {
			logmsg = fmt.Sprintf("[%s][%03d]> %s", IcsLogLevelStr[level], sessionID, msg)
		} else {
			logmsg = fmt.Sprintf("[%s][-1]> %s", IcsLogLevelStr[level], msg)
		}

		l.logger.Output(2, logmsg)
		if l.LogFile != nil {
			l.LogFile.WriteString(l.buf.String())
		}
		l.buf.Reset()

		l.M.Unlock()
	}

}

func (l *IcsLog) Print(level int, sessionID int, msg string) {
	if level >= l.Level {
		//check disk full
		aSpace := icsutil.GetDiskAvailableSpace(filepath.Dir(l.LogFileName))
		if aSpace < uint64(l.conf.Disklimit*ONEMB) {
			//if aSpace < uint64(l.conf.LogConfig.Disklimit*ONEMB) {
			if !l.IsDiskFull {
				msg = fmt.Sprintf("Disk Full! Available Disk Space: %dMB", aSpace/ONEMB)
				l.logger.Output(2, msg)
				if l.LogFile != nil {
					l.LogFile.WriteString(l.buf.String())
				}
				l.buf.Reset()
				l.IsDiskFull = true
			}
			return
		}

		l.M.Lock()

		if l.checkLogRotate() {
			//check log size
			stat, err := os.Stat(l.LogFileName)
			if err != nil {
				msg = fmt.Sprintf("Could not get log file(%s) size", l.LogFileName)
				l.logger.Output(2, msg)
				if l.LogFile != nil {
					l.LogFile.WriteString(l.buf.String())
				}
				l.buf.Reset()

				l.M.Unlock()

				return
			}

			if stat.Size()/ONEMB >= int64(l.logSize) {
				//shift log files
				rotateNum := gIcsLog.getTodayLogFileNum()
				//fmt.Println("rotate num:", rotateNum, "log size:", stat.Size()/ONEMB, l.logSize)
				if rotateNum > 0 && rotateNum < gIcsLog.rotateNum {
					gIcsLog.shiftLogFiles(rotateNum)

					l.LogFile.Sync()
					l.LogFile.Close()

					//open new log file
					var oerr error
					l.LogFile, oerr = os.OpenFile(l.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
					if oerr != nil {
						icserror.ICSERRFileOpen.SetError(oerr)
						icserror.ICSERRFileOpen.PrintWithCaller(1)

						l.M.Unlock()
						return
					}
				} else {
					l.M.Unlock()
					return
				}

			}
		}

		//write log
		if level < LOG_LEVEL_DEBUG2 || level > LOG_LEVEL_FATAL {
			level = LOG_LEVEL_INFO
		}
		var logmsg string
		if sessionID >= 0 {
			logmsg = fmt.Sprintf("[%s][%03d]> %s", IcsLogLevelStr[level], sessionID, msg)
		} else {
			logmsg = fmt.Sprintf("[%s][-1]> %s", IcsLogLevelStr[level], msg)
		}
		l.logger.Output(2, logmsg)
		if l.LogFile != nil {
			l.LogFile.WriteString(l.buf.String())
		}
		l.buf.Reset()

		l.M.Unlock()
	}
}

func (l *IcsLog) PrintAnnouce(msg string, customer bool) {
	//check disk full
	aSpace := icsutil.GetDiskAvailableSpace(filepath.Dir(l.LogFileName))
	if aSpace < uint64(l.conf.Disklimit*ONEMB) {
		//if aSpace < uint64(l.conf.LogConfig.Disklimit*ONEMB) {
		if !l.IsDiskFull {
			msg = fmt.Sprintf("Disk Full! Available Disk Space: %dMB", aSpace/ONEMB)
			l.logger.Output(2, msg)
			if l.LogFile != nil {
				l.LogFile.WriteString(l.buf.String())
			}
			l.buf.Reset()
			l.IsDiskFull = true
		}
		return
	}

	l.M.Lock()

	if l.checkLogRotate() {
		//check log size
		stat, err := os.Stat(l.LogFileName)
		if err != nil {
			msg = fmt.Sprintf("Could not get log file(%s) size", l.LogFileName)
			l.logger.Output(2, msg)
			if l.LogFile != nil {
				l.LogFile.WriteString(l.buf.String())
			}
			l.buf.Reset()

			l.M.Unlock()

			return
		}

		if stat.Size()/ONEMB >= int64(l.logSize) {
			//shift log files
			rotateNum := gIcsLog.getTodayLogFileNum()
			//fmt.Println("rotate num:", rotateNum, "log size:", stat.Size()/ONEMB, l.logSize)
			if rotateNum > 0 && rotateNum < gIcsLog.rotateNum {
				gIcsLog.shiftLogFiles(rotateNum)

				l.LogFile.Sync()
				l.LogFile.Close()

				//open new log file
				var oerr error
				l.LogFile, oerr = os.OpenFile(l.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
				if oerr != nil {
					icserror.ICSERRFileOpen.SetError(oerr)
					icserror.ICSERRFileOpen.PrintWithCaller(0)

					l.M.Unlock()
					return
				}
			} else {
				l.M.Unlock()
				return
			}

		}
	}
	var logmsg string
	if customer {
		logmsg = fmt.Sprintf(">>> %s\n", msg)
	} else {
		logmsg = fmt.Sprintf("<<< %s\n", msg)
	}

	l.logger.Output(2, logmsg)
	if l.LogFile != nil {
		l.LogFile.WriteString(l.buf.String())
	}
	l.buf.Reset()

	l.M.Unlock()
}