#ifndef ACL_MSG_INCLUDE_H
#define ACL_MSG_INCLUDE_H

#ifdef  __cplusplus
extern "C" {
#endif

#include "acl_define.h"
#include <stdarg.h>
#include "acl_vstream.h"

#undef	USE_PRINTF_MACRO

/**
 * ڽд־־ļǰصûԶĺҽ־Ϣݸú
 * ֻеûͨ acl_msg_pre_write úЧ
 * @param ctx {void*} ûԶ
 * @param fmt {const char*} ʽ
 * @param ap {va_list} ʽб
 */
typedef void (*ACL_MSG_PRE_WRITE_FN)(void *ctx, const char *fmt, va_list ap);

/**
 * Ӧͨ˺ͿԶ־򿪺Ӧڴ־ǰ
 * acl_msg_register עԶ򿪺Ӧõ acl_msg_open
 * ʱô˶־־ȱʡķ־ļ
 * @param file_name {const char*} شԶ־򿪺Ĳ
 *  ־ļش
 * @param ctx {void*} ӦôݽȥĲ
 * @return {int} Զ־ -1 ȱʡ־򿪺
 */
typedef int (*ACL_MSG_OPEN_FN) (const char *file_name, void *ctx);

/**
 * Ӧͨ˺ͿԶ־رպӦڴ־ǰ
 * acl_msg_register עԶ򿪺Ӧõ acl_msg_close
 * ʱô˶ر־ر־ȱʡķر־ļ
 * @param ctx {void*} ӦôݽȥĲ
 */
typedef void (*ACL_MSG_CLOSE_FN) (void *ctx);

/**
 * Ӧͨ˺ͿԶ־¼Ӧڴ־ǰ
 * acl_msg_register עԶ¼Ӧд־ʱôԶ
 * ¼־ȱʡ־¼
 * @param ctx {void*} ӦôݽȥĲ
 * @param fmt {const char*} ʽ
 * @param ap {va_list} б
 */
typedef void (*ACL_MSG_WRITE_FN) (void *ctx, const char *fmt, va_list ap);

/**
 * ڴ־ǰô˺עӦԼ־򿪺־رպ־¼
 * @param open_fn {ACL_MSG_OPEN_FN} Զ־򿪺
 * @param close_fn {ACL_MSG_CLOSE_FN} Զ־رպ
 * @param write_fn {ACL_MSG_WRITE_FN} Զ־¼
 * @param ctx {void*} Զ
 */
ACL_API void acl_msg_register(ACL_MSG_OPEN_FN open_fn, ACL_MSG_CLOSE_FN close_fn,
        ACL_MSG_WRITE_FN write_fn, void *ctx);

/**
 *  acl_msg_register עԶ庯ȱʡ־
 */
ACL_API void acl_msg_unregister(void);

/**
 * ڴ־ǰô˺עӦõ˽кڼ¼־ǰȼ¼Ϣͨ
 * עĺݸӦ
 * @param pre_write {ACL_MSG_PRE_WRITE_FN} ־¼ǰõĺ
 * @param ctx {void*} Զ
 */
ACL_API void acl_msg_pre_write(ACL_MSG_PRE_WRITE_FN pre_write, void *ctx);

/**
 * ȫֱʾԼ
 * @DEPRECATED òֻڲʹãⲿӦòӦ
 */
extern ACL_API int acl_msg_verbose;

/**
 * δ acl_msg_open ʽ־ʱ acl_msg_info/error/fatal/warn
 * ĲǷϢ׼Ļϣͨ˺øÿأÿ
 * ӰǷҪϢնĻӰǷļ
 * @param onoff {int}  0 ʾĻ
 */
ACL_API void acl_msg_stdout_enable(int onoff);

/**
 *  acl_msg_error_xxx/acl_msg_warn_xxx Ⱥ¼򾯸͵־ʱ
 * ǷҪ¼öջɸú
 * @param onoff {int}  0 ʾ¼ó/־Ķջȱʡ¼
 */
ACL_API void acl_msg_trace_enable(int onoff);

/**
 * ־򿪺
 * @param log_file {const char*} ־߼ϣ "|" ָ
 *  ǱļԶ׽ӿڣ:
 *  /tmp/test.log|UDP:127.0.0.1:12345|TCP:127.0.0.1:12345|UNIX:/tmp/test.sock
 *  Ҫ־ͬʱ /tmp/test.log, UDP:127.0.0.1:12345,
 *  TCP:127.0.0.1:12345  UNIX:/tmp/test.sock ĸ־
 * @param info_pre {const char*} ־¼ϢǰʾϢ
 */
ACL_API void acl_msg_open(const char *log_file, const char *info_pre);

/**
 * ־򿪺
 * @param fp {ACL_VSTREAM *} ־ļ
 * @param info_pre {const char*} ־¼ϢǰʾϢ
 */
ACL_API void acl_msg_open2(ACL_VSTREAM *fp, const char *info_pre);

/**
 * ر־
 */
ACL_API void acl_msg_close(void);

/**
 * ¼־Ϣ־ļʱҪµ־¼
 */

#ifndef	USE_PRINTF_MACRO

/**
 * һ㼶־Ϣ¼
 * @param fmt {const char*} ʽ
 * @param ... 
 */
ACL_API void ACL_PRINTF(1, 2) acl_msg_info(const char *fmt,...);

/**
 * 漶־Ϣ¼
 * @param fmt {const char*} ʽ
 * @param ... 
 */
ACL_API void ACL_PRINTF(1, 2) acl_msg_warn(const char *fmt,...);

/**
 * 󼶱־Ϣ¼
 * @param fmt {const char*} ʽ
 * @param ... 
 */
ACL_API void ACL_PRINTF(1, 2) acl_msg_error(const char *fmt,...);

/**
 * ־Ϣ¼
 * @param fmt {const char*} ʽ
 * @param ... 
 */
ACL_API void ACL_PRINTF(1, 2) acl_msg_fatal(const char *fmt,...);

/**
 * ־Ϣ¼
 * @param status {int} ǰδ
 * @param fmt {const char*} ʽ
 * @param ... 
 */
ACL_API void ACL_PRINTF(2, 3)
	acl_msg_fatal_status(int status, const char *fmt,...);

/**
 * ֻż־Ϣ¼
 * @param fmt {const char*} ʽ
 * @param ... 
 */
ACL_API void ACL_PRINTF(1, 2) acl_msg_panic(const char *fmt,...);

/**
 * һ㼶־Ϣ¼
 * @param fmt {const char*} ʽ
 * @param ap {va_list} б
 */
ACL_API void acl_msg_info2(const char *fmt, va_list ap);


/**
 * 漶־Ϣ¼
 * @param fmt {const char*} ʽ
 * @param ap {va_list} б
 */
ACL_API void acl_msg_warn2(const char *fmt, va_list ap);

/**
 * 󼶱־Ϣ¼
 * @param fmt {const char*} ʽ
 * @param ap {va_list} б
 */
ACL_API void acl_msg_error2(const char *fmt, va_list ap);


/**
 * ־Ϣ¼
 * @param fmt {const char*} ʽ
 * @param ap {va_list} б
 */
ACL_API void acl_msg_fatal2(const char *fmt, va_list ap);

/**
 * ־Ϣ¼
 * @param status {int} ǰδ
 * @param fmt {const char*} ʽ
 * @param ap {va_list} б
 */
ACL_API void acl_msg_fatal_status2(int status, const char *fmt, va_list ap);

/**
 * ֻż־Ϣ¼
 * @param fmt {const char*} ʽ
 * @param ap {va_list} б
 */
ACL_API void acl_msg_panic2(const char *fmt, va_list ap);
#else

/**
 * ¼־Ϣ׼ʱҪµ־¼
 */

#include <stdio.h>

#undef	acl_msg_info
#undef	acl_msg_warn
#undef	acl_msg_error
#undef	acl_msg_fatal
#undef	acl_msg_panic

#define	acl_msg_info	acl_msg_printf
#define	acl_msg_warn	acl_msg_printf
#define	acl_msg_error	acl_msg_printf
#define	acl_msg_fatal	acl_msg_printf
#define	acl_msg_panic	acl_msg_printf

#endif

/**
 * ڱ׼C strerror, úǿƽ̨̰߳ȫģöӦĳ
 * ŵĴϢ
 * @param errnum {unsigned int} 
 * @param buffer {char*} 洢Ϣڴ滺
 * @param size {int} buffer ĴС
 * @return {const char*} صĵַӦ buffer ͬ
 */
ACL_API const char *acl_strerror(unsigned int errnum, char *buffer, int size);
ACL_API const char *acl_strerror1(unsigned int errnum);

/**
 * ϴϵͳóʱĴϢ
 * @param buffer {char*} 洢Ϣڴ滺
 * @param size {int} buffer ĿռС
 * @return {const char*} صĵַӦ buffer ͬ
 */
ACL_API const char *acl_last_strerror(char *buffer, int size);

/**
 * ϴϵͳóʱĴϢúڲֲ߳̾߳
 * ȫģʹЩ
 * @return {const char *} شʾϢ 
 */
ACL_API const char *acl_last_serror(void);

/**
 * ϴϵͳóʱĴ
 * @return {int} 
 */
ACL_API int acl_last_error(void);

/**
 * ֹô
 * @param errnum {int} 
 */
ACL_API void acl_set_error(int errnum);

/**
 * Ϣ׼
 * @param fmt {const char*} ʽ
 * @param ... 
 */
ACL_API void ACL_PRINTF(1, 2) acl_msg_printf(const char *fmt,...);

#ifdef  __cplusplus
}
#endif

#endif

