/**
 * @file:    $RCSfile: systrace.h,v $
 * @brief:   $System trace API definiens.
 *
 * @version: $Revision: 1.2 $
 * @date:    $Date: 2019/02/19 07:18:52 $
 * @author:  $Author: lizhongming $
 * @state:   $State: Exp $
 *
 * @latest:  $Id: systrace.h,v 1.2 2019/02/19 07:18:52 lizhongming Exp $
 */

#ifndef _SAS_TRACE_H_
#define _SAS_TRACE_H_

#define SASLOG_DEBUG			(0)
#define SASLOG_WARN				(1)
#define SASLOG_ERROR			(2)

#define ANSI_TEXT_NORMAL        "0"
#define ANSI_TEXT_HIGHLIGHT     "1"
#define ANSI_TEXT_BLINK         "5"

#define ANSI_COLOR_BLACK        "30m"
#define ANSI_COLOR_RED          "31m"
#define ANSI_COLOR_GREEN        "32m"
//高亮下有效
#define ANSI_COLOR_BROWN        "33m"
#define ANSI_COLOR_BLUE         "34m"
//高亮下有效
#define ANSI_COLOR_PINK         "35m"
#define ANSI_COLOR_LIGHTBLUE    "36m"
#define ANSI_COLOR_WHITE        "37m"

#define ANSI_COLOR_NORMAL       "0m"

#ifdef  _OS_UNIX_
#define ERROR_HIGHLIGHT_BEGIN   "\033[1m\033[31m\033[40m"
#define ERROR_HIGHLIGHT_END     "\033[0m"
#define WARN_HIGHLIGHT_BEGIN    "\033[32m\033[40m"
#define WARN_HIGHLIGHT_END      "\033[0m"
#else
#define ERROR_HIGHLIGHT_BEGIN   ""
#define ERROR_HIGHLIGHT_END     ""  
#define WARN_HIGHLIGHT_BEGIN    ""
#define WARN_HIGHLIGHT_END      ""
#endif

APR_DECLARE_DATA extern uint32_t g_addition_log;
APR_DECLARE_DATA extern int g_tmp_debug ;

//warn
#define echo_warn(s) \
    echo_msg_warnex(__FILE__,__LINE__,("%s"),s)
#define echo_warn1(fmt,s0) \
    echo_msg_warnex(__FILE__,__LINE__,(fmt),(s0))
#define echo_warn2(fmt,s0,s1) \
    echo_msg_warnex(__FILE__,__LINE__,(fmt),(s0),(s1))
#define echo_warn3(fmt,s0,s1,s2) \
    echo_msg_warnex(__FILE__,__LINE__,(fmt),(s0),(s1),(s2))
#define echo_warn4(fmt,s0,s1,s2,s3) \
    echo_msg_warnex(__FILE__,__LINE__,(fmt),(s0),(s1),(s2),(s3))
#define echo_warn5(fmt,s0,s1,s2,s3,s4) \
    echo_msg_warnex(__FILE__,__LINE__,(fmt),(s0),(s1),(s2),(s3),(s4))
#define echo_warn6(fmt,s0,s1,s2,s3,s4,s5) \
    echo_msg_warnex(__FILE__,__LINE__,(fmt),(s0),(s1),(s2),(s3),(s4),(s5))
#define echo_warn7(fmt,s0,s1,s2,s3,s4,s5,s6) \
    echo_msg_warnex(__FILE__,__LINE__,(fmt),(s0),(s1),(s2),(s3),(s4),(s5),(s6))
#define echo_warn8(fmt,s0,s1,s2,s3,s4,s5,s6,s7) \
    echo_msg_warnex(__FILE__,__LINE__,(fmt),(s0),(s1),(s2),(s3),(s4),(s5),(s6),(s7))
#define echo_warn9(fmt,s0,s1,s2,s3,s4,s5,s6,s7,s8) \
    echo_msg_warnex(__FILE__,__LINE__,(fmt),(s0),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8))
#define echo_warn10(fmt,s0,s1,s2,s3,s4,s5,s6,s7,s8,s9) \
    echo_msg_warnex(__FILE__,__LINE__,(fmt),(s0),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8),(s9))
#define echo_warn11(fmt,s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10) \
    echo_msg_warnex(__FILE__,__LINE__,(fmt),(s0),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8),(s9),(s10))
#define echo_warn12(fmt,s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11) \
    echo_msg_warnex(__FILE__,__LINE__,(fmt),(s0),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8),(s9),(s10),(s11))

//err
#define echo_err(s,rv) \
    echo_msg_errex(__FILE__,__LINE__,(rv),("%s"),(s))
#define echo_errg(s) \
    echo_msg_errex(__FILE__,__LINE__,(APR_EGENERAL),("%s"),(s))
#define echo_err1(fmt,rv,s1) \
    echo_msg_errex(__FILE__,__LINE__,(rv),(fmt),(s1))
#define echo_err2(fmt,rv,s1,s2) \
    echo_msg_errex(__FILE__,__LINE__,(rv),(fmt),(s1),(s2))
#define echo_err3(fmt,rv,s1,s2,s3) \
    echo_msg_errex(__FILE__,__LINE__,(rv),(fmt),(s1),(s2),(s3))
#define echo_err4(fmt,rv,s1,s2,s3,s4) \
    echo_msg_errex(__FILE__,__LINE__,(rv),(fmt),(s1),(s2),(s3),(s4))
#define echo_err5(fmt,rv,s1,s2,s3,s4,s5) \
    echo_msg_errex(__FILE__,__LINE__,(rv),(fmt),(s1),(s2),(s3),(s4),(s5))
#define echo_err6(fmt,rv,s1,s2,s3,s4,s5,s6) \
    echo_msg_errex(__FILE__,__LINE__,(rv),(fmt),(s1),(s2),(s3),(s4),(s5),(s6))
#define echo_err7(fmt,rv,s1,s2,s3,s4,s5,s6,s7) \
    echo_msg_errex(__FILE__,__LINE__,(rv),(fmt),(s1),(s2),(s3),(s4),(s5),(s6),(s7))
#define echo_err8(fmt,rv,s1,s2,s3,s4,s5,s6,s7,s8) \
    echo_msg_errex(__FILE__,__LINE__,(rv),(fmt),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8))
#define echo_err9(fmt,rv,s1,s2,s3,s4,s5,s6,s7,s8,s9) \
    echo_msg_errex(__FILE__,__LINE__,(rv),(fmt),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8),(s9))
#define echo_err10(fmt,rv,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10) \
    echo_msg_errex(__FILE__,__LINE__,(rv),(fmt),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8),(s9),(s10))
#define echo_err11(fmt,rv,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11) \
    echo_msg_errex(__FILE__,__LINE__,(rv),(fmt),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8),(s9),(s10),(s11))
#define echo_err12(fmt,rv,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12) \
    echo_msg_errex(__FILE__,__LINE__,(rv),(fmt),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8),(s9),(s10),(s11),(s12))

//msg
#define echo_msg(s) \
    echo_msg_debugex(__FILE__,__LINE__,("%s"),(s))
#define echo_msg1(fmt,s1) \
    echo_msg_debugex(__FILE__,__LINE__,(fmt),(s1))
#define echo_msg2(fmt,s1,s2) \
    echo_msg_debugex(__FILE__,__LINE__,(fmt),(s1),(s2))
#define echo_msg3(fmt,s1,s2,s3) \
    echo_msg_debugex(__FILE__,__LINE__,(fmt),(s1),(s2),(s3))
#define echo_msg4(fmt,s1,s2,s3,s4) \
    echo_msg_debugex(__FILE__,__LINE__,(fmt),(s1),(s2),(s3),(s4))
#define echo_msg5(fmt,s1,s2,s3,s4,s5) \
    echo_msg_debugex(__FILE__,__LINE__,(fmt),(s1),(s2),(s3),(s4),(s5))
#define echo_msg6(fmt,s1,s2,s3,s4,s5,s6) \
    echo_msg_debugex(__FILE__,__LINE__,(fmt),(s1),(s2),(s3),(s4),(s5),(s6))
#define echo_msg7(fmt,s1,s2,s3,s4,s5,s6,s7) \
    echo_msg_debugex(__FILE__,__LINE__,(fmt),(s1),(s2),(s3),(s4),(s5),(s6),(s7))
#define echo_msg8(fmt,s1,s2,s3,s4,s5,s6,s7,s8) \
    echo_msg_debugex(__FILE__,__LINE__,(fmt),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8))
#define echo_msg9(fmt,s1,s2,s3,s4,s5,s6,s7,s8,s9) \
    echo_msg_debugex(__FILE__,__LINE__,(fmt),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8),(s9))
#define echo_msg10(fmt,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10) \
    echo_msg_debugex(__FILE__,__LINE__,(fmt),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8),(s9),(s10) )
#define echo_msg11(fmt,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11) \
    echo_msg_debugex(__FILE__,__LINE__,(fmt),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8),(s9),(s10),(s11))
#define echo_msg12(fmt,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12) \
    echo_msg_debugex(__FILE__,__LINE__,(fmt),(s1),(s2),(s3),(s4),(s5),(s6),(s7),(s8),(s9),(s10),(s11),(s12))


#define MON_SEND			0			/**< 通讯监视方向发送 */
#define MON_RECV			1			/**< 通讯监视方向接收 */

#define MON_COM				1			/**< 端口类型串口 */
#define MON_TCP				2			/**< 端口类型TCP  */
#define MON_UDP				3			/**< 端口类型UDP  */
#define	MON_LOG				4			/**< 信息类型　　 */

#define LEVEL_NORMAL		1			/**< 正常LOG等级 */
#define LEVEL_WARN			2			/**< 告警LOG等级 */
#define LEVEL_ERROR			3			/**< 错误LOG等级 */

#define MON_HEADER_LEN		22
#define MTRACEBUFLEN		3000		/**< 每次可以Trace的最大数据长度 */

typedef struct trace_t trace_t;
struct trace_t {
    apr_pool_t			*pool;
	//apr_pool_t			*addr_pool;
    apr_socket_t		*sockdes;
    apr_sockaddr_t		*addr;
    apr_thread_mutex_t	*mutex;
};

typedef struct LOGSTAS LOGSTAS;
struct LOGSTAS {  
    byte_t		debug:1;
    byte_t		warn:1;
	byte_t		error:1;
	byte_t		log3:1;
	byte_t		log4:1;
	byte_t		log5:1;
	byte_t		res:2;
}ALIGNPACKED;
typedef struct log_config_t log_config_t;
struct log_config_t{
    char		*msg_cache;
	LOGSTAS		status;
	uint32_t	log_udp_ip;
	uint32_t	DiffHostFromIp;
};

#ifdef _OS_WIN32_
#pragma pack(push,1)   
#endif 

typedef struct monbuf_t monbuf_t;
struct monbuf_t {
	byte_t		sync_code[4];			/**< 同步字 EB 90 EB 90 */
	byte_t		ied_len;				/**< 装置名称长度 */
	byte_t		orient;					/**< 监视的方向：MON_SEND / MON_RECV */
	byte_t		type;					/**< 端口类型：MON_COM / MON_TCP / MON_UDP */
	byte_t		node_len;				/**< 节点名称长度 */
	uint32_t	node_id;				/**< 节点号  */
	uint32_t	ied_id;					/**< 装置号 */
	uint32_t	localhost;				/**< TCP或UDP时表示本机IP地址 */
	uint32_t	remotehost;				/**< TCP或UDP时表示对端IP地址 */
	uint16_t	localport;				/**< TCP或UDP时表示本机端口号 */
	uint16_t	remoteport;				/**< TCP或UDP时表示对端端口号 */
	uint32_t	len;					/**< 有效数据长度(数据**data的长度) */
	byte_t		node_name[32];			/**< 节点名称 */
	byte_t		ied_name[32];			/**< 装置名称 */
	byte_t		serial_name[16];		/**< 串口名称 */
	byte_t		serial_len;				/**< 串口名称长度 */
    byte_t		data[MTRACEBUFLEN+10];	/**< 待发送数据数据缓冲区 */
	//在待发送数据数据缓冲区后增加四字节(uint32_t)，用于代表主备机及多机
}ALIGNPACKED;

#ifdef _OS_WIN32_
#pragma pack(pop)    
#endif

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/**
* @brief 在UNIX环境下，输出带颜色的文本
* @param foreground   前景色           
* @param background   背景色
* @param str 要输出的文本
*/
APR_DECLARE(void) echo_color(char * foreground,char * background,char * str);

APR_DECLARE(int) trace_driver_create(trace_t * t,char * ip,apr_port_t port,apr_pool_t * pool);

APR_DECLARE(int) trace_driver_destory(trace_t * t);

APR_DECLARE(int) trace_driver_send(trace_t * t,const char * msg, apr_size_t len);

APR_DECLARE(apr_status_t) create_log_handle(apr_pool_t * pool);

APR_DECLARE(log_config_t *) get_log_handle(void);

APR_DECLARE(void) echo_msg_debugex(char * file_name,int line_no,char *fmt,...);

APR_DECLARE(void) echo_msg_warnex(char * file_name,int line_no, char *fmt,...);

APR_DECLARE(void) echo_msg_errex(char * file_name,int line_no,apr_status_t rv, char *fmt,...);

APR_DECLARE(int) trace_data(byte_t type, 
							byte_t orient,	 
                             uint32_t localhost,
							 uint32_t localport,
                             uint32_t remotehost,
							 uint32_t remoteport,
							 const char *serial_name,
							 int serial_len,
							 uint32_t node_id,
							 const char *node_name,
							 int node_len,
							 uint32_t client_id,
							 uint32_t ied_id,
							 const char *ied_name,
							 int ied_len,
                             const char *buf,
							 int len,
							 uint32_t traceIp);        

/**
* @brief 将TCP或UDP数据发送给通信报文监视程序
* @param type   被监视的端口类型：MON_TCP / MON_UDP
* @param orient 被监视的数据发送方向：MON_SEND / MON_RECV
* @param connect 被监视的本地连接
* @param node_id 被监视的NODE节点号
* @param node_name 被监视的NODE节点名称
* @param ied_id 被监视的NODE节点中某IED的IED号
* @param ied_name 被监视的NODE节点中某IED的IED名称
* @param buf 被监视的数据缓冲区
* @param len 被监视的有效数据长度
* @param client_id 节点号
* @param traceIp 点对点UDP发送端
*/
APR_DECLARE(void) trace_connect_buf(byte_t type,byte_t orient,void *connect,
									uint32_t node_id,const char *node_name,uint32_t client_id,
									uint32_t ied_id,const char *ied_name,
									const char *buf,int len,uint32_t traceIp);

/**
* @brief 将windows串口数据发送给通信报文监视程序
* @param orient 被监视的数据发送方向：MON_SEND / MON_RECV
* @param serial_port 被监视的串口号
* @param node_id 被监视的NODE节点号
* @param node_name 被监视的NODE节点名称
* @param ied_id 被监视的NODE节点中某IED的IED号
* @param ied_name 被监视的NODE节点中某IED的IED名称
* @param buf 被监视的数据缓冲区
* @param len 被监视的有效数据长度
* @param client_id 客户端节点号
* @param traceIp 点对点UDP发送端
*/
APR_DECLARE(void) trace_wserial_buf(byte_t orient,int serial_port,
									uint32_t node_id,const char *node_name,uint32_t client_id,
									uint32_t ied_id,const char *ied_name,
									const char *buf,int len,uint32_t traceIp);

/**
* @brief 将linux串口数据发送给通信报文监视程序
* @param orient 被监视的数据发送方向：MON_SEND / MON_RECV
* @param serial_name 被监视的串口名称
* @param node_id 被监视的NODE节点号
* @param node_name 被监视的NODE节点名称
* @param ied_id 被监视的NODE节点中某IED的IED号
* @param ied_name 被监视的NODE节点中某IED的IED名称
* @param buf 被监视的数据缓冲区
* @param len 被监视的有效数据长度
* @param client_id 客户端节点号
* @param traceIp 点对点UDP发送端
*/
APR_DECLARE(void) trace_serial_buf(byte_t orient,const char *serial_name,
									uint32_t node_id,const char *node_name,uint32_t client_id,
									uint32_t ied_id,const char *ied_name,
									const char *buf,int len,uint32_t traceIp);

APR_DECLARE(void) trace_log_buf(byte_t level,uint32_t m_id,uint32_t client_id,const char *m_name,int ied_len,const char *buf,int len,uint32_t traceIp);

APR_DECLARE(void) trace_tmp_debug(int node_id,char *str);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif 
