/*
** Job Arranger for ZABBIX
** Copyright (C) 2025 Daiwa Institute of Research Ltd. All Rights Reserved.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
**/
package main

/*
// Define corresponding C enum
typedef enum {
    LOG_LEVEL_INFO  = 0,
    LOG_LEVEL_CRIT  = 1,
    LOG_LEVEL_ERR   = 2,
    LOG_LEVEL_WARN  = 3,
    LOG_LEVEL_DEBUG = 4
} CLogLevel;

typedef enum {
    LOG_TYPE_FILE    = 0,
    LOG_TYPE_SYSTEM  = 1,
    LOG_TYPE_CONSOLE = 2
} CLogType;

*/
import "C"
import (
	"unsafe"

	"jobarranger2/src/libs/golibs/common"
	"jobarranger2/src/libs/golibs/logger/logger"
)

// Export the enum values as C-compatible functions
//
//export GetLogLevelInfo
func GetLogLevelInfo() C.CLogLevel {
	return C.CLogLevel(logger.LogLevelInfo)
}

//export GetLogLevelCrit
func GetLogLevelCrit() C.CLogLevel {
	return C.CLogLevel(logger.LogLevelCrit)
}

//export GetLogLevelErr
func GetLogLevelErr() C.CLogLevel {
	return C.CLogLevel(logger.LogLevelErr)
}

//export GetLogLevelWarn
func GetLogLevelWarn() C.CLogLevel {
	return C.CLogLevel(logger.LogLevelWarn)
}

//export GetLogLevelDebug
func GetLogLevelDebug() C.CLogLevel {
	return C.CLogLevel(logger.LogLevelDebug)
}

//export InitLogger
func InitLogger(logFilePath *C.char, messageFilePath *C.char, logTypeStr *C.char, maxLogFileSize C.int, logLevelInt C.int, targetType C.int, cErrMsg *C.char, size C.int) C.int {
	err := logger.InitLogger(C.GoString(logFilePath), C.GoString(messageFilePath), C.GoString(logTypeStr), int(maxLogFileSize), int(logLevelInt), int(targetType))

	if err != nil {
		setStrFromGoToC(err.Error(), cErrMsg, size)
		return -1
	}

	return 0

}

// It finds the message by id and store the value in messageStr
// FindMessageByID returns:
// -2 = ignore the log due to log level
// -1 = error
//
//	0 = no notification
//	1 = needs notification
//
//export FindMessageByID
func FindMessageByID(messageID *C.char, cLogLevel *C.CLogLevel, msgStr *C.char, msgStrSize C.int, cErrMsg *C.char, size C.int) C.int {
	msg, err := logger.FindMessage(C.GoString(messageID))
	if err != nil {
		setStrFromGoToC(err.Error(), cErrMsg, size)
		return -1
	}

	if logger.ShouldIgnoreLog(msg.LogLevel) {
		return -2
	}

	*cLogLevel = C.CLogLevel(msg.LogLevel)

	setStrFromGoToC(msg.Body, msgStr, msgStrSize)

	return C.int(msg.NoticeFlag)
}

//export WriteLog
func WriteLog(cLogLevel C.CLogLevel, message *C.char, cErrMsg *C.char, size C.int) int {
	err := logger.WriteLogHelper(logger.LogLevel(cLogLevel), C.GoString(message))
	if err != nil {
		setStrFromGoToC(err.Error(), cErrMsg, size)
		return -1
	}

	return 0
}

//export CreateNotiEvent
func CreateNotiEvent(message *C.char, messageID *C.char, cLogLevel C.CLogLevel, cErrMsg *C.char, size C.int) int {
	if err := logger.CreateNotiEvent(common.ZbxSendInfo{
		LogMessage:   C.GoString(message),
		LogMessageID: C.GoString(messageID),
		LogLevel:     int(cLogLevel),
	}); err != nil {
		setStrFromGoToC(err.Error(), cErrMsg, size)
		return -1
	}

	return 0
}

// Set error message to the C char array
func setStrFromGoToC(errMsg string, cErrMsg *C.char, size C.int) {
	// Check max length to be greater than zero
	maxLength := int(size) - 1
	if maxLength <= 0 {
		return
	}

	// Truncate the message if overflow
	msgBytes := []byte(errMsg)

	if len(msgBytes) >= maxLength {
		msgBytes = msgBytes[:maxLength]
	}

	// Create a slice that references the C memory
	destSlice := unsafe.Slice((*byte)(unsafe.Pointer(cErrMsg)), maxLength)

	// Copy the value
	copy(destSlice, msgBytes)

	// Ensure null-termination
	destSlice[len(msgBytes)] = 0
}

func main() {
}
