package log

/*
#cgo CFLAGS: -fvisibility=hidden
#cgo LDFLAGS:-lpthread -ldl -lstdc++ -lrt -lm -lc -lz -luv -lcjson -luvdbus -lcurl -lcrypto -ldbus-1 -lsqlite3 -ls2json -lquickmail -luuid -lcutils -lconfig
#include <stdlib.h>
#include <uvdbus/log.h>
*/
import "C"

import (
	"flag"
	"fmt"
	"io/ioutil"
	"netease_control_center/utils/glog"
	"os"
	"strings"
	"time"
	"unsafe"
)

const (
	FLUSH_INTERVAL  = 2 * time.Second // 刷新glog的缓存
	COUNT_THRESHOLD = 2

	//BACK_LOG_FILES_DIR = "/mnt/UDISK/glogBack/"
	BACK_LOG_FILES_DIR = "/tmp/dglog/" // for test

	INITIAL_DATE = "197001"
)

var (
	newlyModifyTIme int64 = 0

	countForProLogFiles uint8 = 0 // 对计数，达到阈值处理日志文件

	KillLog bool = false
)

type Level uint8

const (
	DebugLog Level = iota
	WarningLog
	ErrorLog
	FatalLog
	numSeverity = 5
)

func Init() {
	err := os.MkdirAll(BACK_LOG_FILES_DIR, os.ModePerm)
	if nil != err {
		fmt.Println("create glogBack dir:", err)
	}

	// 初始化命令行参数，glog模块需要用到
	flag.Parse()

	glog.SetOutStdLevel(uint8(DebugLog))

	//　在control的timer中统一处理一些定时器任务
	//go logFilesProDemon()
}

func Println(level Level, e ...interface{}) {
	args := fmt.Sprintln(e...)
	updateLog2Server(level, args)

	if KillLog {
		return
	}
	switch level {
	case DebugLog:
		// debug 消息打印时，需要传入参数　--v=1
		if !glog.V(1) {
			return
		}
	case WarningLog, ErrorLog, FatalLog:
		if !glog.V(0) {
			return
		}
	default:

	}

	switch level {
	case DebugLog:
		glog.Debug(e...)
	case WarningLog:
		glog.Warning(e...)
	case ErrorLog:
		glog.Error(e...)
	case FatalLog:
		glog.Fatal(e...)
	default:
		glog.Error("err level:", level)
	}
}

func Printf(level Level, format string, args ...interface{}) {
	argsStr := fmt.Sprintf(format, args...)
	updateLog2Server(level, argsStr)

	if KillLog {
		return
	}
	switch level {
	case DebugLog:
		// debug 消息打印时，需要传入参数　--v=1
		if !glog.V(1) {
			return
		}
	case WarningLog, ErrorLog, FatalLog:
		if !glog.V(0) {
			return
		}
	default:

	}
	switch level {
	case DebugLog:
		glog.Debugf(format, args...)
	case WarningLog:
		glog.Warningf(format, args...)
	case ErrorLog:
		glog.Errorf(format, args...)
	case FatalLog:
		glog.Fatalf(format, args...)
	default:
		glog.Error("err level:", level)
	}
}

func updateLog2Server(level Level, args string) {
	argsCptr := C.CString(args)
	var levelC C.int
	switch level {
	case DebugLog:
		levelC = 8
	case WarningLog:
		levelC = 4
	case ErrorLog:
		levelC = 2
	case FatalLog:
		levelC = 1
	default:

	}
	C.IHW_LogStrWithoutPrint(levelC, argsCptr)
	C.free(unsafe.Pointer(argsCptr))

	//fmt.Printf("level:%d args:%+v\n", levelC, args)
}

/**
 * 处理本地的日志文件，目前的处理逻辑是删除当天之外的所有日志文件
 */
func logFilesProDemon() {
	for _ = range time.NewTicker(FLUSH_INTERVAL * (COUNT_THRESHOLD + 1)).C {
		LogDaemon()
	}
}

func LogFlushAll() {
	glog.FlushAll()
}

func LogDaemon() {
	glog.FlushAll()

	if countForProLogFiles < COUNT_THRESHOLD {
		countForProLogFiles++
		return
	} else {
		countForProLogFiles = 0
	}

	processLogFiles()
	return
}

func processLogFiles() {
	curDate := time.Now().Format("200601")
	//Println(DebugLog, "processLogFiles curDate:", curDate)

	dir, err := ioutil.ReadDir(glog.DefalutLogDir)
	if err != nil {
		return
	}

	for _, fi := range dir {
		if (strings.Contains(fi.Name(), curDate) || strings.Contains(fi.Name(), INITIAL_DATE)) &&
			fi.ModTime().Unix() > newlyModifyTIme {
			newlyModifyTIme = fi.ModTime().Unix()
		}
	}

	for _, fi := range dir {
		if fi.IsDir() { // 忽略目录
			continue
		}

		if (strings.Contains(fi.Name(), curDate) || strings.Contains(fi.Name(), INITIAL_DATE)) &&
			fi.ModTime().Unix() < newlyModifyTIme {

			//fileName := C.CString(glog.DefalutLogDir + fi.Name())
			//Println(ErrorLog, "backup:", fi.Name(), " fileName:", fileName)
			//C.UploadLogFile(fileName)
			//C.free(unsafe.Pointer(fileName))
			//os.Remove(glog.DefalutLogDir + fi.Name())

			Println(ErrorLog, "backup:", fi.Name())
			os.Remove(glog.DefalutLogDir + fi.Name())
		}
	}
}
