/********************************************************************
Copyright ?2007 LGC Wireless, Inc. All rights reserved
File Name: 		aifg_debug.c
Description:	Source file of debug submodule of AIFG
Version:		v9.0.0
Author:			Roy Jiang
Create Date:	2007-3-22

History:
2007-3-22		v9.0.0	Create
*********************************************************************/
#include "./include/aifg_msg.h"
#include "./include/aifg_var_ext.h"
#include "../../debug/src/include/debug.h"

static char help_info[] = "AIFG debug help:\r\n\
log all                         Turn on all debug information\r\n\
log none                        Turn off all information\r\n\
log error on/off                Turn on/off error information\r\n\
log event on/off                Turn on/off event information\r\n\
list circuit group              Print circuit group Table\r\n\
list sap                        Print SAP information\r\n\
list port                       Print opened port\r\n\
list link                       Print opened link\r\n\
wa port x                       Watch port x\r\n\
wa link x                       Watch link x\r\n\
msg stat                        Show message statistics\r\n\
clear msg stat                  Clear message statistics\r\n\
";

const char *msg_name[] = {
	"TRANSPARENT DTAP MESSAGE",
	"PAGING RESPONSE",
	"RR HANDOVER COMMAND",
	"IMSI DETACH INDICATION",
	"LOCATION UPDATING ACCEPT",
	"LOCATION UPDATING REJECT",
	"LOCATION UPDATING REQUEST",
	"AUTHENTICATION REJECT",
	"AUTHENTICATION REQUEST",
	"AUTHENTICATION RESPONSE",
	"IDENTITY REQUEST",
	"IDENTITY RESPONSE",
	"TMSI REALLOCATION COMMAND",
	"TMSI REALLOCATION COMPLETE",
	"CM SERVICE ACCEPT",
	"CM SERVICE REJECT",
	"CM SERVICE ABORT",
	"CM SERVICE REQUEST",
	"CM SERVICE PROMPT",
	"CM RE-ESTABLISHMENT REQUEST",
	"ABORT",
	"MM NULL",
	"MM STATUS",
	"MM INFORMATION",
	"ALERTING",
	"CALL CONFIRMED",
	"CALL PROCEEDING",
	"CONNECT",
	"CONNECT ACK",
	"EMERGENCY SETUP",
	"PROGRESS",
	"SETUP",
	"MODIFY",
	"MODIFY COMPLETE",
	"MODIFY REJECT",
	"USER INFORMATION",
	"HOLD",
	"HOLD ACK",
	"HOLD REJECT",
	"RETRIEVE",
	"RETRIEVE ACK",
	"RETRIEVE REJECT",
	"DISCONNECT",
	"RELEASE",
	"RELEASE COMPLETE",
	"CONGESTION CONTROL",
	"NOTIFY",
	"STATUS",
	"STATUS ENQUIRY",
	"START DTMF",
	"STOP DTMF",
	"STOP DTMF ACK",
	"START DTMF ACK",
	"START DTMF REJECT",
	"FACILITY",
	"FACILITY SS",
	"REGISTER",
	"RELEASE COMPLETED SS",
	"RP-DATA",
	"RP-ACK",
	"RP-ERROR",
	"RP-SMMA",
	"BLOCK",
	"BLOCKING ACK",
	"UNBLOCK",
	"UNBLOCKING ACK",
	"CIRCUIT GROUP BLOCK",
	"CIRCUIT GROUP BLOCK ACK",
	"CIRCUIT GROUP UNBLOCK",
	"CIRCUIT GROUP UNBLOCK ACK",
	"RESOURCE REQUEST",
	"RESOURCE INDICATION",
	"RESET",
	"RESET ACK",
	"PAGING",
	"OVERLOAD",
	"RESET CIRCUIT",
	"RESET CIRCUIT ACK",
	"HANDOVER CANDIDATE ENQUIRE",
	"HANDOVER CANDIDATE RESPONSE",
	"ASSIGN REQUEST",
	"ASSIGN COMPLETE",
	"ASSIGN FAILURE",
	"HANDOVER REQUEST",
	"HANDOVER REQUIRED",
	"HANDOVER REQUEST ACK",
	"HANDOVER COMMAND",
	"HANDOVER COMPLETE",
	"HANDOVER SUCCEEDED",
	"HANDOVER FAILURE",
	"HANDOVER PERFORMED",
	"HANDOVER REQUIRED REJECT",
	"HANDOVER DETECT",
	"CLEAR COMMAND",
	"CLEAR COMPLETE",
	"CLEAR REQUEST",
	"SAPI 'N' REJECT",
	"CONFUSION",
	"SUSPEND",
	"RESUME",
	"LOCATION INFORMATION COMMAND",
	"LOCATION INFORMATION REPORT",
	"MSC INVOKE TRACE",
	"BSC INVOKE TRACE",
	"UNEQUIPPED CIRCUIT",
	"CHANGE CIRCUIT",
	"CHANGE CIRCUIT ACK",
	"CIPHER MODE COMMAND",
	"CLASSMARK UPDATE",
	"CIPHER MODE COMPLETE",
	"QUEUEING INDICATION",
	"COMPLETE LAYER 3 INFORMATION",
	"CLASSMARK REQUEST",
	"CIPHER MODE REJECT",
	"LOAD INDICATION",
	"LSA INFORMATION",
	NULL,//reserved
	NULL,//reserved
	NULL,//reserved
	NULL,//reserved
	NULL,//reserved
	NULL,//reserved
	NULL,//reserved
	NULL,//reserved
	NULL,//reserved
	NULL,//reserved
	NULL,//reserved
	NULL,//reserved
	NULL,//reserved
};

const char *sap_name[] = {
	"MSC",
	"BSC"
};

const char *ni_name[] = {
	"NATIONAL",
	"NATIONAL SPARE",
	"INTERNATIONAL",
	"INTERNATIONAL SPARE",
};

static const char *normal = "\033[0m";
static const char *red = "\033[0;31;40m";
static const char *green = "\033[0;32;40m";
static const char *yellow = "\033[0;33;40m";
//static const char *blue = "\033[0;34;40m";

#define AIFG_DEBUG_MAX_LEN 8192
static char debug_buf[AIFG_DEBUG_MAX_LEN];
static char asc_in[256];
static struct log_flag_t{
	BYTE all;
	BYTE err;
	BYTE evt;
}log_flag;

int msg_statistics[AIFG_MAX_MESSAGE][2];

void aifg_parsecmd();
char *sprint_msg_content(char *dst, BYTE *msg, int msg_len);

void aifg_debug_init()
{
	char aifg_ver[] = "R9V0_05P2";
    DWORD ascout_id[20] = { 1, 3, 6, 1, 4, 1, 1373, 1, 3, 2, 3, 1, 2, 23, 4 };
    DWORD ascin_id[20] = { 1, 3, 6, 1, 4, 1, 1373, 1, 3, 2, 3, 1, 2, 23, 3 };
    DWORD status_id[20] = { 1, 3, 6, 1, 4, 1, 1373, 1, 3, 2, 3, 1, 2, 23, 1 };
    DWORD name_id[20] = { 1, 3, 6, 1, 4, 1, 1373, 1, 3, 2, 3, 1, 2, 23, 2 };
    BYTE debug_status = 1;

    debug_set_response (15, ascout_id, debug_buf, AIFG_DEBUG_MAX_LEN);
    debug_set_response (15, ascin_id, asc_in, 1);
    debug_set_response (15, status_id, &debug_status, 1);
    debug_set_response (15, name_id, aifg_ver, strlen(aifg_ver));

	memset(msg_statistics, 0, sizeof(msg_statistics));
}

void aifg_debug_timer()
{
    BYTE npage;

    if(strlen(asc_in) <= 1)
        return;
        
    debug_buf[0] = '\0';
    npage = asc_in[0] - 1;
    if(npage == 0){
        aifg_parsecmd(asc_in + 1);
        asc_in[0] = '\0';
        return;
    }

    switch (npage){
 		default:
        break;
    }
    asc_in[0] = '\0';
}

/*
Purpose:	Print debug information
Input:		aifg_event_code event: event code
			void *msg: message pointer, will be convert to aifg_msg_t* or aifg_predecode_msg* 
					or SP_UiPriPara* according to different event
			int o_info: other information, differ from event code
Outpur:		none
*/
void aifg_debug_print(int port, aifg_event_code event, void *msg, int o_info)
{
	char buffer[1024];
	struct timeval tv;
    struct timezone tz;
    struct tm *t;
    char timestr[1024];

	if(log_flag.all != 1){
		if (port == -1 || aifg_pcb[port].trace_flag == 0)
		{
			if((event >= 1024) && (log_flag.evt != 1))
				goto FINISH;
			else if (log_flag.err != 1)
				goto FINISH;
		}		
	}	

    gettimeofday ( &tv, &tz );
    t = localtime ( &tv.tv_sec );
    sprintf ( timestr, "(%d:%d:%d.%ld):", t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec );
	
	switch(event){
		case AIFG_SUCCEED:
			goto FINISH;
			break;
		case AIFG_ERROR:
			sprintf(buffer, "%sUnknown error!%s\n",red, normal);
			break;
		//error
		case AIFG_ERR_OUT_OF_RESOURCE:
			sprintf(buffer, "%sAIFG ALARM: Out of resources!%s\n",red, normal);
			break;
		case AIFG_ERR_UNKNOW_MSG:
			sprintf(buffer, "%sAIFG ERROR: Unknow message received!%s\n",red, normal);
			break;
		case AIFG_ERR_UNKNOW_IE:
			sprintf(buffer, "%sAIFG ERROR: Unknow IE in received message!%s\n",red, normal);
			break;
		case AIFG_ERR_ERROR_MSG:
			sprintf(buffer, "%sAIFG ERROR: Dameged message received!%s\n",red, normal);
			break;
		case AIFG_ERR_ERROR_IE:
			sprintf(buffer, "%sERROR: Dameged IE in received message!%s\n",red, normal);
			break;
		case AIFG_ERR_UP_NOT_EXIST:
			sprintf(buffer, "%sERROR: Can not find the request SAP for received message!%s\n",red, normal);
			break;
		case AIFG_ERR_NO_UD_IN_CR:
			sprintf(buffer, "%sERROR: CR received without user data field%s\n",red, normal);
			break;
		case AIFG_ERR_UNEXPECTED_DT1:
			sprintf(buffer, "%sERROR: Unexpected DT1 received!%s\n",red, normal);
			break;
		case AIFG_ERR_UNEXPECTED_UDT:
			sprintf(buffer, "%sERROR: Unexpected UDT received!%s\n",red, normal);
			break;
		case AIFG_ERR_UNEXPECTED_PAGING_RESP:
			sprintf(buffer, "%sERROR: Unexpected Paging Response received!%s\n",red, normal);
			break;
		case AIFG_ERR_INVALID_TI:
			{
				aifg_msg_pre_decoded *pMsg = (aifg_msg_pre_decoded *)msg;
				sprintf(buffer, "%sERROR: Invalid TI in message %s, link %d! %s\n", 
					red, 
					msg_name[pMsg->id],
					o_info,
					normal);
			}			
			break;
		case AIFG_ERR_MISS_MANDATORY:
			{
				aifg_msg_pre_decoded *pMsg = (aifg_msg_pre_decoded *)msg;
				sprintf(buffer, "%sERROR: Damaged message %s, missing mandatory! %s\n", 
					red, 
					msg_name[pMsg->id],
					normal);
			}	
			break;
		case AIFG_ERR_MSG_RV_TO_IDLE_PORT:
			{
				aifg_msg_pre_decoded *pMsg = (aifg_msg_pre_decoded *)msg;
				sprintf(buffer, "%sERROR: Message %s received from link %d for IDLE port %d!%s\n",
					red, 
					msg_name[pMsg->id],
					aifg_pcb[pMsg->aif_port].link_id,
					pMsg->aif_port,
					normal);
			}			
			break;
		case AIFG_ERR_MSG_SD_TO_IDLE_PORT:
			{
				aifg_msg_t *pMsg = (aifg_msg_t *)msg;
				sprintf(buffer, "%sERROR: Application send message %s to IDLE port %d!%s\n",
					red, 
					msg_name[pMsg->id],
					pMsg->aif_port,
					normal);
			}			
			break;
		case AIFG_ERR_ASSIGN_PORT_FAIL:
			sprintf(buffer, "%sERROR: Port assign failed, resource limited! Upper port %d %s\n",red, o_info, normal);
			break;
		case AIFG_ERR_SAP_NOT_CREATED:
			sprintf(buffer, "%sERROR: Upper port %d send message refused, SAP not created!%s\n",red, o_info, normal);
			break;
		case AIFG_ERR_PORT_TIMER_OUT:
			sprintf(buffer, "%sERROR: PORT %d Protocol time out! Start release transaction.%s\n",red, o_info, normal);
			break;
		case AIFG_ERR_CAN_NOT_FIND_TI:
			sprintf(buffer, "%sERROR: PORT %d Can not find TI for the transaction! Transaction released.%s\n",red, o_info, normal);
			break;
		case AIFG_ERR_PAGING_NOT_RESP:
			sprintf(buffer, "%sERROR: PORT %d Paging no response!.%s\n",red, o_info, normal);
			break;
		case AIFG_ERR_PORT_RELEASED:
			{
				char tmp_cause_string[64];
				aifg_msg_pre_decoded *pMsg = (aifg_msg_pre_decoded *)msg;

				if (pMsg->cause == 0x09 || pMsg->cause == 0x0B)
					goto FINISH;	//normal release
				else if (pMsg->cause == 0x66)
					strcpy(tmp_cause_string, "Timer expired");
				else if (pMsg->cause == 0x6F)
					strcpy(tmp_cause_string, "Protocol error");
				else 
					tmp_cause_string[0] = '\0';

				sprintf(buffer, "%sERROR: Port %d, Cause: %d, %s, send release ind to app port %d %s\n", 
					red,
					pMsg->aif_port,
					pMsg->cause,
					tmp_cause_string,
					aifg_pcb[pMsg->aif_port].upper_port,
					normal
				);
			}
			break;

		//event
		case AIFG_EVENT_REDIR_MSG:
			sprintf(buffer, "AIFG EVENT: Message directed to the other server!\n");
			break;
		case AIFG_EVENT_LINK_RELEASE:
			sprintf(buffer, "Link %d released!\n", o_info);
			break;
		case AIFG_EVENT_PORT_RELEASE:
			sprintf(buffer, "Port %d released!\n", o_info);
			break;
		case AIFG_EVENT_RV_MSG:
			{
				aifg_msg_pre_decoded *pMsg = (aifg_msg_pre_decoded *)msg;
				int msg_id = pMsg->id;
				if (msg_id == AIFG_MSG_ID_L3_INFO)
					msg_id = pMsg->msg.completeL3Info.l3msg.id;
				
				sprintf(buffer, "%sSCCP => AIFG: ID: %s, APP_PORT:%d, AIFG_PORT:%d, LINK_ID:%d%s\n", 
					green,
					msg_name[msg_id],
					aifg_pcb[pMsg->aif_port].upper_port,
					pMsg->aif_port,
					aifg_pcb[pMsg->aif_port].link_id,
					normal
					);
			}
			break;
			
		case AIFG_EVENT_SD_MSG:
			{
				aifg_msg_t *pMsg = (aifg_msg_t *)msg;
 				sprintf(buffer, "%sAIFG => SCCP: ID: %s, APP_PORT:%d, AIFG_PORT:%d, LINK_ID:%d%s\n", 
 					yellow,
 					msg_name[pMsg->id],
					pMsg->app_port,
 					pMsg->aif_port,
 					aifg_pcb[pMsg->aif_port].link_id,
 					normal
 					);
			}
			break;
		default:
			goto FINISH;
			break;
	}	
	aifg_log(strcat(timestr, buffer));
	
FINISH:
	aifg_event = AIFG_SUCCEED;
	return;
}

void aifg_get_open_port(int flag)
{
	int i = 0, j = 0;
	char tmp_buf[20];
	char buf[1024];
	buf[0] = '\0';

	for (i=0; i < AIFG_MAX_PORT; i++){
		if(aifg_pcb[i].stat != 0){
			if(j % 16 == 0 && j != 0){
				aifg_log(buf);
				buf[0] = '\0';
			}
			sprintf(tmp_buf,"%d\t", i);
			strcat(buf, tmp_buf);
			j++;
		}
	}
}

void aifg_get_open_link(int flag)
{
	int i = 0, j = 0;
	char tmp_buf[20];
	char buf[1024];
	buf[0] = '\0';
	for (i = 0; i < SCCP_MAX_LINK; i++){
		if(link_info[i].en_flag != 0){
			if(j % 16 == 0 && j != 0){
				aifg_log(buf);
				buf[0] = '\0';
			}
			sprintf(tmp_buf,"%d\t", i);
			strcat(buf, tmp_buf);
			j++;
		}
	}
}

void aifg_get_sap()
{
	char buf[1024];
	sprintf(buf, "Current opened SAP: \n");
	
	if(sap[0].enable != 0)
		strcat(buf, "MSC\t");
	if(sap[1].enable != 0)
		strcat(buf, "BSC");

	aifg_log(buf);

	return;
}

void aifg_debug_get_cg()
{
	int i = 0;
	char tmp_buf[20];
	char buf[1024];
	int flag = 0;

	sprintf(buf, "#\t\t SAP\t\t NI\t\t DPC\n");
	for (i = 0; i < AIFG_MAX_CG; i++){
		if(cg[i].enable != 0){
			sprintf(tmp_buf,"%03d\t\t", i);
			strcat(buf, tmp_buf);
			
			if (cg[i].sapid == 0)
				sprintf(tmp_buf,"MSC\t\t");
			else
				sprintf(tmp_buf,"BSC\t\t");
			strcat(buf, tmp_buf);
			
			sprintf(tmp_buf,"%02d\t\t", cg[i].ni);
			strcat(buf, tmp_buf);

			sprintf(tmp_buf,"%d\n", cg[i].dpc);
			strcat(buf, tmp_buf);

			flag = 1;
		}
	}
	if (flag == 0)
		aifg_log("No Circuit Group enabled!");
	else
		aifg_log(buf);

	return;
}

void aifg_print_port_info(int i, int flag)
{
	char buf[1024];
	char imsi[32];

	sprintf(buf, 
"=======AIFG Port %d=======\r\n\
stat: %d\r\n\
sapid: %d\r\n\
cgid: %d\r\n\
linkid: %d\r\n\
new_link: %d\r\r\
app_port: \%d\r\n\
timer: %d\r\n\
ti: %d\r\n\
ti_type: %d\r\n\
ti_stat: %d\r\n\
ho_stat: %d\r\n\
app_ho_port: %d\r\n\
rel_cause: %d\r\n\
imsi: %s\r\n\
pNextOpenPort: %d\r\n\
pPrevOpenPort: %d\r\n\
pNextPort: %d\r\n\
pPrevPort: %d\r\n\
==========================\n",
		i,
		aifg_pcb[i].stat,
		aifg_pcb[i].sapid,
		aifg_pcb[i].cgid,
		aifg_pcb[i].link_id,
		aifg_pcb[i].new_link,
		aifg_pcb[i].upper_port,
		aifg_pcb[i].timer,
		aifg_pcb[i].ti,
		aifg_pcb[i].ti_type,
		aifg_pcb[i].ti_stat,
		aifg_pcb[i].ho_stat,
		aifg_pcb[i].app_ho_port,
		aifg_pcb[i].rel_cause,
		sprint_msg_content(imsi, aifg_pcb[i].imsi, aifg_pcb[i].imsi_len),
		aifg_pcb[i].pNextOpenPort - aifg_pcb,
		aifg_pcb[i].pPrevOpenPort - aifg_pcb,
		aifg_pcb[i].pNextPort - aifg_pcb,
		aifg_pcb[i].pPrevPort - aifg_pcb);

	if(flag == 0)
		aifg_log(buf);
	else
		printf(buf);
}

void aifg_print_link_info(int i, int flag){
	char buf[1024];

	sprintf(buf, 
"=======AIFG Link %d=======\r\n\
en_flag: %d\r\n\
sapid: %d\r\n\
cur_port: \%d\r\n\
ti_number: %d\r\n\
==========================\n",
		i,
		link_info[i].en_flag,
		link_info[i].sapid,
		link_info[i].cur_port,
		link_info[i].ti_number);

	if(flag == 0)
		aifg_log(buf);
	else
		printf(buf);
}

void aifg_print_msg_stat()
{
	char msg_str[32];
	char tmpbuf[1024];
	int i, j;
	int max_name_length = 28;

	aifg_log("==========================AIFG Message Statistics==========================\r\n"
		"Message                     \t\t  Sent \t\t\t Received");

	for(i=0; i < AIFG_MAX_MESSAGE; i++){
		if (msg_name[i] == NULL)
			break;

		j = max_name_length - strlen(msg_name[i]);
		sprintf(msg_str, "%s", msg_name[i]);
		while(j-- > 0)
			strcat(msg_str, " ");

		sprintf(tmpbuf, "%s\t  %10d    \t    %10d", msg_str, msg_statistics[i][1], msg_statistics[i][0]);
		aifg_log(tmpbuf);
	}
}

void aifg_parsecmd(char *cmdstr)
{
    if(strstr (cmdstr, "help") != NULL || strstr (cmdstr, "?") != NULL)
        aifg_log(help_info);
	else if(strstr (cmdstr, "log all") != NULL)
		log_flag.all = 1;
	else if(strstr (cmdstr, "log none") != NULL)
		memset(&log_flag, 0, sizeof(log_flag));
	else if(strstr (cmdstr, "log event on") != NULL)
		log_flag.evt = 1;
	else if(strstr (cmdstr, "log event off") != NULL)
		log_flag.evt = 0;
	else if(strstr (cmdstr, "log error on") != NULL)
		log_flag.err = 1;
	else if(strstr (cmdstr, "log error off") != NULL)
		log_flag.err = 0;
	else if(strstr (cmdstr, "list port") != NULL)
		aifg_get_open_port(0);
	else if(strstr (cmdstr, "list link") != NULL)
		aifg_get_open_link(0);
	else if(strstr (cmdstr, "list sap") != NULL)
		aifg_get_sap();
	else if(strstr (cmdstr, "list cg") != NULL)
		aifg_debug_get_cg();
	else if(strstr (cmdstr, "wa port ") != NULL){
		int i = atoi(cmdstr+8);
		if (i < AIFG_MAX_PORT)
			aifg_print_port_info(i, 0);
	}
	else if(strstr (cmdstr, "wa link ") != NULL){
		int i = atoi(cmdstr+8);
		if (i < SCCP_MAX_LINK)
			aifg_print_link_info(i, 0);
	}
	else if (strstr (cmdstr, "clear msg stat") != NULL){
		memset(msg_statistics, 0, sizeof(msg_statistics));
	}
	else if (strstr (cmdstr, "msg stat") != NULL){
		aifg_print_msg_stat();
	}
	else{
		char tmp_buffer[100];
		sprintf(tmp_buffer, "%sInvalid Command!%s\n",red, normal);
		aifg_log(tmp_buffer);
		return;
	}

    aifg_log("Command OK.");
    return;
}

void aifg_log(char *info)
{
	if(strlen(debug_buf) + strlen(info) > AIFG_DEBUG_MAX_LEN)
	{
//		aifgDebugFull = 1;
		return;
	}

	strncat(debug_buf, info, AIFG_DEBUG_MAX_LEN);
	strcat(debug_buf, "\r\n");
	return;
}

static u8 	ascii[16] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
						 0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};
char *sprint_msg_content(char *dst, BYTE *msg, int msg_len)
{
	int	i = 0;
	int j = 0;

	j += 9;
	for (i = 0; i < msg_len; i++)
	{
		dst[j++] = ascii[msg[i] >> 4];
		dst[j++] = ascii[msg[i] & 0x0f];
		dst[j++] =  ' ';

		if(i % 15 == 0 && i != 0){
			memcpy(dst+j, "\n         ", 9);
			j += 10;
		}
		else if(i % 7 == 0 && i != 0){
			dst[j++] = ' ';
		}
	}
	dst[j++] = '\n';
	dst[j] = '\0';

	return dst;
}

#if 0
/********************************************************************
Copyright ?2007 LGC Wireless, Inc. All rights reserved
File Name: 		aifg_debug.c
Description:	Source file of debug submodule of AIFG
Version:		v9.0.0
Author:			Roy Jiang
Create Date:	2007-3-22

History:
2007-3-22		v9.0.0	Create
*********************************************************************/
#include "./include/aifg_msg.h"
#include "./include/aifg_var_ext.h"
#include "../../debug/src/include/debug.h"
#include "../../debug/src/include/debug_r9.h"

static char help_info[] = "AIFG debug help:\r\n\
						  log all                         Turn on all debug information\r\n\
						  log none                        Turn off all information\r\n\
						  log error on/off                Turn on/off error information\r\n\
						  list circuit group              Print circuit group Table\r\n\
						  list sap                        Print SAP information\r\n\
						  list port                       Print opened port\r\n\
						  list link                       Print opened link\r\n\
						  wa port x                       Watch port x\r\n\
						  wa link x                       Watch link x\r\n\
						  ";

const char *msg_name[] = {
	"",
	"PAGING RESPONSE",
	"RR HANDOVER COMMAND",
	"IMSI DETACH INDICATION",
	"LOCATION UPDATING ACCEPT",
	"LOCATION UPDATING REJECT",
	"LOCATION UPDATING REQUEST",
	"AUTHENTICATION REJECT",
	"AUTHENTICATION REQUEST",
	"AUTHENTICATION RESPONSE",
	"IDENTITY REQUEST",
	"IDENTITY RESPONSE",
	"TMSI REALLOCATION COMMAND",
	"TMSI REALLOCATION COMPLETE",
	"CM SERVICE ACCEPT",
	"CM SERVICE REJECT",
	"CM SERVICE ABORT",
	"CM SERVICE REQUEST",
	"CM SERVICE PROMPT",
	"CM RE-ESTABLISHMENT REQUEST",
	"ABORT",
	"MM NULL",
	"MM STATUS",
	"MM INFORMATION",
	"ALERTING",
	"CALL CONFIRMED",
	"CALL PROCEEDING",
	"CONNECT",
	"CONNECT ACK",
	"EMERGENCY SETUP",
	"PROGRESS",
	"SETUP",
	"MODIFY",
	"MODIFY COMPLETE",
	"MODIFY REJECT",
	"USER INFORMATION",
	"HOLD",
	"HOLD ACK",
	"HOLD REJECT",
	"RETRIEVE",
	"RETRIEVE ACK",
	"RETRIEVE REJECT",
	"DISCONNECT",
	"RELEASE",
	"RELEASE COMPLETE",
	"CONGESTION CONTROL",
	"NOTIFY",
	"STATUS",
	"STATUS ENQUIRY",
	"START DTMF",
	"STOP DTMF",
	"STOP DTMF ACK",
	"START DTMF ACK",
	"START DTMF REJECT",
	"FACILITY",
	"FACILITY SS",
	"REGISTER",
	"RELEASE COMPLETED SS",
	"RP-DATA",
	"RP-ACK",
	"RP-ERROR",
	"RP-SMMA",
	"BLOCK",
	"BLOCKING ACK",
	"UNBLOCK",
	"UNBLOCKING ACK",
	"CIRCUIT GROUP BLOCK",
	"CIRCUIT GROUP BLOCK ACK",
	"CIRCUIT GROUP UNBLOCK",
	"CIRCUIT GROUP UNBLOCK ACK",
	"RESOURCE REQUEST",
	"RESOURCE INDICATION",
	"RESET",
	"RESET ACK",
	"PAGING",
	"OVERLOAD",
	"RESET CIRCUIT",
	"RESET CIRCUIT ACK",
	"HANDOVER CANDIDATE ENQUIRE",
	"HANDOVER CANDIDATE RESPONSE",
	"ASSIGN REQUEST",
	"ASSIGN COMPLETE",
	"ASSIGN FAILURE",
	"HANDOVER REQUEST",
	"HANDOVER REQUIRED",
	"HANDOVER REQUEST ACK",
	"HANDOVER COMMAND",
	"HANDOVER COMPLETE",
	"HANDOVER SUCCEEDED",
	"HANDOVER FAILURE",
	"HANDOVER PERFORMED",
	"HANDOVER REQUIRED REJECT",
	"HANDOVER DETECT",
	"CLEAR COMMAND",
	"CLEAR COMPLETE",
	"CLEAR REQUEST",
	"SAPI 'N' REJECT",
	"CONFUSION",
	"SUSPEND",
	"RESUME",
	"LOCATION INFORMATION COMMAND",
	"LOCATION INFORMATION REPORT",
	"MSC INVOKE TRACE",
	"BSC INVOKE TRACE",
	"UNEQUIPPED CIRCUIT",
	"CHANGE CIRCUIT",
	"CHANGE CIRCUIT ACK",
	"CIPHER MODE COMMAND",
	"CLASSMARK UPDATE",
	"CIPHER MODE COMPLETE",
	"QUEUEING INDICATION",
	"COMPLETE LAYER 3 INFORMATION",
	"CLASSMARK REQUEST",
	"CIPHER MODE REJECT",
	"LOAD INDICATION",
	"LSA INFORMATION",
	};

const char *sap_name[] = {
	"MSC",
	"BSC"
	};

const char *ni_name[] = {
	"NATIONAL",
	"NATIONAL SPARE",
	"INTERNATIONAL",
	"INTERNATIONAL SPARE",
	};

char aifg_ver[] = "R9V0_03A";

static const char *normal = "\033[0m";
static const char *red = "\033[0;31;40m";
static const char *green = "\033[0;32;40m";
static const char *yellow = "\033[0;33;40m";
static const char *blue = "\033[0;34;40m";

static char debug_buf[4096];
static char new_debug_buf[4096];
static char asc_in[256];

static int LOG_ERR_ID;
static int AIFG_DBEUG_SAPID;

void aifg_parsecmd();
char *sprint_msg_content(char *dst, BYTE *msg, int msg_len);
void aifg_debug_r9_init();

void aifg_debug_init()
	{
	DWORD status_id[20] = { 1, 3, 6, 1, 4, 1, 1373, 1, 3, 2, 3, 1, 2, 23, 1 };
	DWORD name_id[20] = { 1, 3, 6, 1, 4, 1, 1373, 1, 3, 2, 3, 1, 2, 23, 2 };
	BYTE debug_status = 1;

	debug_set_response (15, status_id, &debug_status, 1);
	debug_set_response (15, name_id, aifg_ver, strlen(aifg_ver));

	aifg_debug_r9_init();
	}

void aifg_debug_timer()
	{
	BYTE npage, nline;

	switch (npage){
		default:
			break;
		}
	}

/*
Purpose:	Print debug information
Input:		aifg_event_code event: event code
void *msg: message pointer, will be convert to aifg_msg_t* or aifg_predecode_msg* 
or SP_UiPriPara* according to different event
int o_info: other information, differ from event code
Outpur:		none
*/
void aifg_debug_print(aifg_event_code event, void *msg, int o_info)
	{
	char buffer[1024];
	struct timeval tv;
	struct timezone tz;
	struct tm *t;
	char timestr[1024];

	gettimeofday ( &tv, &tz );
	t = localtime ( &tv.tv_sec );
	sprintf ( timestr, "(%d:%d:%d.%ld):", t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec );

	switch(event){
		case AIFG_SUCCEED:
			goto FINISH;
			break;
		case AIFG_ERROR:
			sprintf(buffer, "%sUnknown error!%s\n",red, normal);
			break;
			//error
		case AIFG_ERR_OUT_OF_RESOURCE:
			sprintf(buffer, "%sAIFG ALARM: Out of resources!%s\n",red, normal);
			break;
		case AIFG_ERR_UNKNOW_MSG:
			sprintf(buffer, "%sAIFG ERROR: Unknown message received!%s\n",red, normal);
			break;
		case AIFG_ERR_UNKNOW_IE:
			sprintf(buffer, "%sAIFG ERROR: Unknown IE in received message!%s\n",red, normal);
			break;
		case AIFG_ERR_ERROR_MSG:
			sprintf(buffer, "%sAIFG ERROR: Damaged message received!%s\n",red, normal);
			break;
		case AIFG_ERR_ERROR_IE:
			sprintf(buffer, "%sERROR: Damaged IE in received message!%s\n",red, normal);
			break;
		case AIFG_ERR_UP_NOT_EXIST:
			sprintf(buffer, "%sERROR: Can not find the request SAP for received message!%s\n",red, normal);
			break;
		case AIFG_ERR_NO_UD_IN_CR:
			sprintf(buffer, "%sERROR: CR received without user data field%s\n",red, normal);
			break;
		case AIFG_ERR_UNEXPECTED_DT1:
			sprintf(buffer, "%sERROR: Unexpected DT1 received!%s\n",red, normal);
			break;
		case AIFG_ERR_UNEXPECTED_UDT:
			sprintf(buffer, "%sERROR: Unexpected UDT received!%s\n",red, normal);
			break;
		case AIFG_ERR_UNEXPECTED_PAGING_RESP:
			sprintf(buffer, "%sERROR: Unexpected Paging Response received!%s\n",red, normal);
			break;
		case AIFG_ERR_INVALID_TI:
			{
			aifg_msg_pre_decoded *pMsg = (aifg_msg_pre_decoded *)msg;
			sprintf(buffer, "%sERROR: Invalid TI in message %s, link %d! %s\n", 
				red, 
				msg_name[pMsg->id],
				o_info,
				normal);
			}			
			break;
		case AIFG_ERR_MISS_MANDATORY:
			{
			aifg_msg_pre_decoded *pMsg = (aifg_msg_pre_decoded *)msg;
			sprintf(buffer, "%sERROR: Damaged message %s, missing mandatory! %s\n", 
				red, 
				msg_name[pMsg->id],
				normal);
			}	
			break;
		case AIFG_ERR_MSG_RV_TO_IDLE_PORT:
			{
			aifg_msg_pre_decoded *pMsg = (aifg_msg_pre_decoded *)msg;
			sprintf(buffer, "%sERROR: Message %s received from link %d for IDLE port %d!%s\n",
				red, 
				msg_name[pMsg->id],
				aifg_pcb[pMsg->aif_port].link_id,
				pMsg->aif_port,
				normal);
			}

			break;
		case AIFG_ERR_MSG_SD_TO_IDLE_PORT:
			{
			aifg_msg_t *pMsg = (aifg_msg_t *)msg;
			sprintf(buffer, "%sERROR: Application send message %s to IDLE port %d!%s\n",
				red, 
				msg_name[pMsg->id],
				pMsg->aif_port,
				normal);
			}

			break;

			//event
		case AIFG_EVENT_REDIR_MSG:
			sprintf(buffer, "AIFG EVENT: Message directed to the other server!\n");
			break;
		case AIFG_EVENT_LINK_RELEASE:
			sprintf(buffer, "Link %d released!\n", o_info);
			break;
		case AIFG_EVENT_RV_MSG:
			{
			aifg_msg_pre_decoded *pMsg = (aifg_msg_pre_decoded *)msg;
			sprintf(buffer, "%sSCCP => AIFG: ID: %s, APP_PORT:%d, AIFG_PORT:%d, LINK_ID:%d%s,\n", 
				green,
				msg_name[pMsg->id],
				aifg_pcb[pMsg->aif_port].upper_port,
				pMsg->aif_port,
				aifg_pcb[pMsg->aif_port].link_id,
				normal
				);
			}
			break;

		case AIFG_EVENT_SD_MSG:
			{
			aifg_msg_t *pMsg = (aifg_msg_t *)msg;
			sprintf(buffer, "%sAIFG => SCCP: ID: %s, APP_PORT:%d, AIFG_PORT:%d, LINK_ID:%d%s\n", 
				yellow,
				msg_name[pMsg->id],
				pMsg->app_port,
				pMsg->aif_port,
				aifg_pcb[pMsg->aif_port].link_id,
				normal
				);
			}
			break;
		default:
			goto FINISH;
			break;
		}	
	debug_print_ascii(AIFG_DBEUG_SAPID, strcat(timestr, buffer));

FINISH:
	aifg_event = AIFG_SUCCEED;
	return;
	}

void aifg_print_error(int err_code)
	{

	}

char *aifg_get_open_port(int flag)
	{
	int i = 0, j = 0;
	char tmp_buf[10];
	new_debug_buf[0] = '\0';
	while (i < AIFG_MAX_PORT){
		if(aifg_pcb[i].stat != 0){
			if(j % 16 == 15)
				sprintf(tmp_buf,"\n%d\t", i);
			else
				sprintf(tmp_buf,"%d\t", i);
			strcat(new_debug_buf, tmp_buf);
			j++;
			}
		i++;
		}

	//	if(flag == 0)
	//		aifg_log(new_debug_buf);

	return new_debug_buf;
	}

char *aifg_get_open_link(int flag)
	{
	int i = 0, j = 0;
	char tmp_buf[10];
	new_debug_buf[0] = '\0';
	while (i < SCCP_MAX_LINK){
		if(link_info[i].en_flag != 0){
			if(j % 16 == 15)
				sprintf(tmp_buf,"\n%d\t", i);
			else
				sprintf(tmp_buf,"%d\t", i);
			strcat(new_debug_buf, tmp_buf);
			j++;
			}
		i++;
		}

	//	if(flag == 0)
	//		aifg_log(new_debug_buf);

	return new_debug_buf;
	}

char *aifg_print_port_info(int i, int flag)
	{
	char imsi[32];

	sprintf(new_debug_buf, 
		"=======AIFG Port %d=======\r\n\
		stat: %d\r\n\
		sapid: %d\r\n\
		cgid: %d\r\n\
		linkid: %d\r\n\
		new_link: %d\r\r\
		app_port: \%d\r\n\
		timer: %d\r\n\
		ti: %d\r\n\
		ti_type: %d\r\n\
		ti_stat: %d\r\n\
		ho_stat: %d\r\n\
		app_ho_port: %d\r\n\
		rel_cause: %d\r\n\
		pNextOpenPort: %d\r\n\
		pPrevOpenPort: %d\r\n\
		pNextPort: %d\r\n\
		pPrevPort: %d\r\n\
		==========================\n",
		i,
		aifg_pcb[i].stat,
		aifg_pcb[i].sapid,
		aifg_pcb[i].cgid,
		aifg_pcb[i].link_id,
		aifg_pcb[i].new_link,
		aifg_pcb[i].upper_port,
		aifg_pcb[i].timer,
		aifg_pcb[i].ti,
		aifg_pcb[i].ti_type,
		aifg_pcb[i].ti_stat,
		aifg_pcb[i].ho_stat,
		aifg_pcb[i].app_ho_port,
		aifg_pcb[i].rel_cause,
		aifg_pcb[i].pNextOpenPort - aifg_pcb,
		aifg_pcb[i].pPrevOpenPort - aifg_pcb,
		aifg_pcb[i].pNextPort - aifg_pcb,
		aifg_pcb[i].pPrevPort - aifg_pcb);

	//	if(flag == 0)
	//		aifg_log(new_debug_buf);

	return new_debug_buf;
	}

char *aifg_print_link_info(int i, int flag){
	sprintf(new_debug_buf, 
		"=======AIFG Link %d=======\r\n\
		en_flag: %d\r\n\
		sapid: %d\r\n\
		cur_port: \%d\r\n\
		ti_number: %d\r\n\
		ti[0] port: %d\r\n\
		ti[1] port: %d\r\n\
		ti[2] port: %d\r\n\
		ti[3] port: %d\r\n\
		ti[4] port: %d\r\n\
		ti[5] port: %d\r\n\
		ti[6] port: %d\r\n\
		ti[7] port: %d\r\n\
		ti[8] port: %d\r\n\
		ti[9] port: %d\r\n\
		ti[10] port: %d\r\n\
		ti[11] port: %d\r\n\
		ti[12] port: %d\r\n\
		ti[13] port: %d\r\n\
		ti[14] port: %d\r\n\
		ti[15] port: %d\r\n\
		==========================\n",
		i,
		link_info[i].en_flag,
		link_info[i].sapid,
		link_info[i].cur_port,
		link_info[i].ti_number,
		link_info[i].ti[0].port,
		link_info[i].ti[1].port,
		link_info[i].ti[2].port,
		link_info[i].ti[3].port,
		link_info[i].ti[4].port,
		link_info[i].ti[5].port,
		link_info[i].ti[6].port,
		link_info[i].ti[7].port,
		link_info[i].ti[8].port,
		link_info[i].ti[9].port,
		link_info[i].ti[10].port,
		link_info[i].ti[11].port,
		link_info[i].ti[12].port,
		link_info[i].ti[13].port,
		link_info[i].ti[14].port,
		link_info[i].ti[15].port);

	//if(flag == 0)
	//	aifg_log(new_debug_buf);

	return new_debug_buf;
	}

char *aifg_print_cg()
	{
	int i;
	char tmp_buf[256];
	sprintf(new_debug_buf, "Current enabled circuit group:\r\n");
	strcat(new_debug_buf, "CG_ID\t\tDPC\t\tNI\n");
	for (i=0; i < AIFG_MAX_CG; i++){
		if (cg[i].enable != 0){
			sprintf(tmp_buf, "%d\t\t%d\t\t%s\n", i, cg[i].dpc, ni_name[cg[i].ni]);
			}		
		}
	strcat(new_debug_buf, tmp_buf);
	return new_debug_buf;
	}
//DEBUG R9------------------------------------------------------------------------------------------------------------
char *aifg_debug_help()
	{
	return help_info;
	}

static int watach_param_port;
static int watach_param_link;
char *aifg_debug_watch(int param_id, int value)
	{
	if (value < 0){
		sprintf(debug_buf, "Illegal parameter value!\n");
		return debug_buf;
		}

	if (param_id == watach_param_port){
		return aifg_print_port_info(value, 1);
		}
	else if (param_id == watach_param_link){
		return aifg_print_link_info(value, 1);
		}
	else{
		assert(0);
		return NULL;
		}
	}

static int list_param_port;
static int list_param_link;
static int list_param_cg;
char *aifg_debug_list(int param_id, int value)
	{
	int i;
	if (param_id == list_param_port){
		return aifg_get_open_port(1);
		}
	else if (param_id == list_param_link){
		return aifg_get_open_link(1);
		}
	else if (param_id == list_param_cg){
		return aifg_print_cg();
		}	
	else{
		assert(0);
		return NULL;
		}
	}

void aifg_debug_r9_init()
	{
	int cmdid, paramid;
	AIFG_DBEUG_SAPID = debug_bind("AIF", "R9V03A");
	cmdid = debug_add_cmd(AIFG_DBEUG_SAPID, "help", aifg_debug_help);

	//cmd watch
	cmdid = debug_add_cmd(AIFG_DBEUG_SAPID, "wa", aifg_debug_watch);
	watach_param_port = debug_add_cmd_param(AIFG_DBEUG_SAPID, cmdid, "port");
	watach_param_link = debug_add_cmd_param(AIFG_DBEUG_SAPID, cmdid, "link");

	//cmd list
	cmdid = debug_add_cmd(AIFG_DBEUG_SAPID, "list", aifg_debug_list);
	list_param_port = debug_add_cmd_param(AIFG_DBEUG_SAPID, cmdid, "port");
	list_param_link = debug_add_cmd_param(AIFG_DBEUG_SAPID, cmdid, "link");
	list_param_cg = debug_add_cmd_param(AIFG_DBEUG_SAPID, cmdid, "cg");

	//add log
	LOG_ERR_ID = debug_add_log(AIFG_DBEUG_SAPID, "error");
	}

#endif
