#include	<stdlib.h>
#include	<stdio.h>

#include    "../include/ppsm.h"
#include    "../include/ramdata.h"
#include    "../include/param.h"

#include    "../include/plat_inc.h"

/*----------------------------------------*/

extern _ram_data			*ramshm_ptr;
extern _state_machine		*smshm_ptr;
extern u_char				logMsgFlag;
extern struct				timeval tvnow;
/*----------------------------------------*/
int pps_debug_map_msg();
/*----------------------------------------*/
extern int PutLogFunID();
extern int stuff_sccp_address();
extern int ppsBcdToAsciiR();
extern int DebugMsg();
extern int DebugMsgDelimiter();
extern int ppsAsciiToBcdR();
extern 	void 	StringCut(char *str, int c);
extern int pps_get_ucbc_number(char *ucbc_number);
extern	PPSParamStruct	ppsParam;
extern u8 isdn_ston(u8 *normal_isdn, u8 *str_isdn);
extern void isdn_ntoa(u8 * anti_isdn, u8 * normal_isdn);
/*----------------------------------------*/

int pps_send_map_open(u_short portid)
{
	u_char	data_flow[256];
	char	msisdn[32];
	int		offset = 0;
	SCCP_ADDR srcAddr,dstAddr;

	 _state_data    *shmp=(_state_data *)&smshm_ptr->state_data;

	PutLogFunID("pps_send_map_open");
		
	shmp += portid;
	shmp->context_info.map_did = map_get_dialogueid(147);
			
	data_flow[offset++] = 0;
	data_flow[offset++] = 1;
	data_flow[offset++] = MAP_FLAG;
	data_flow[offset++] = portid>>8;
	data_flow[offset++] = portid;
	data_flow[offset++] = 0;
	data_flow[offset++] = shmp->context_info.map_did>>8;
	data_flow[offset++] = shmp->context_info.map_did;
	data_flow[offset++] = 0;
	data_flow[offset++] = MAP_OPEN;
	data_flow[offset++] = MAP_REQUEST;

	if(shmp->process_info.routing_home_flag == 1)
	{
		char ucbc_number[32];
		data_flow[offset++] = AC_roamingNbEnquiry;
		
		pps_get_ucbc_number(ucbc_number);
		stuff_sccp_address(&dstAddr,ucbc_number,7, 0);
		shmp->context_info.map_acn_ver = 2; //map_get_acnver(&dstAddr,AC_roamingNbEnquiry);			
		data_flow[offset++] = 2; //AC_roamingNbEnquiry;	
	}
	else
	{
		data_flow[offset++] = shmp->context_info.map_acn;

		stuff_sccp_address(&dstAddr,shmp->called_info.number,6,14);
		shmp->context_info.map_acn_ver = map_get_acnver(&dstAddr,
			AC_anyTimeInfoEnquiry);			
		data_flow[offset++] = shmp->context_info.map_acn_ver;
	}
	
	memcpy(&data_flow[offset],&dstAddr,sizeof(SCCP_ADDR ));
	offset += sizeof(SCCP_ADDR);	
	
	ppsBcdToAsciiR(msisdn,&ppsParam.ppsNumber[1],20);
	StringCut(msisdn,'F');			
	stuff_sccp_address(&srcAddr,msisdn,147,0);
	memcpy(&data_flow[offset],&srcAddr,sizeof(SCCP_ADDR ));	
	offset += sizeof(SCCP_ADDR);
	
	data_flow[offset++] = 0x10; /* delimiter */
	data_flow[offset++] = 0x00; 
	data_flow[1] = offset - 2;

	if((logMsgFlag == 0xff) || shmp->process_info.logMsisdn)
	{
			DebugMsg(debugmib.display.asciiOut,
				"portid: %d ,did: %d, Send Map Open @ %ld.%ld",
				portid,shmp->context_info.map_did,
				tvnow.tv_sec,tvnow.tv_usec);
			pps_debug_map_msg(data_flow,1);
	}	
	return map_send_comdata(data_flow);
		
}

int pps_send_map_openrsp(u_short portid, u_char result)
{
	u_char	msg_flow[256];
	int		did,offset=0;
	_state_data		*shmp = (_state_data *) smshm_ptr->state_data;    

	if(portid>=MAX_FSM_PROCESS)
	{
		return -1;
	}
	shmp += (portid);
	
	did = shmp->context_info.map_did;
	msg_flow[offset++] = 0;
	msg_flow[offset++] = 0;
	msg_flow[offset++] = MAP_FLAG;
	msg_flow[offset++] = portid>>8;
	msg_flow[offset++] = portid;
	msg_flow[offset++] = 0;
	msg_flow[offset++] = did>>8;
	msg_flow[offset++] = did;
	msg_flow[offset++] = 0;
	msg_flow[offset++] = MAP_OPEN;
	msg_flow[offset++] = MAP_RESPONSE;
	msg_flow[offset++] = result;
	if(result == OpenResultAccept)
	{
		msg_flow[offset++] = 0x00;		
	}
	else
	{
		msg_flow[offset++] = 0x01;
		msg_flow[offset++] = 0x03; 
		msg_flow[offset++] = 0x01;
		msg_flow[offset++] = InvalidDesReference;
	}
	
	msg_flow[offset++] = 0x00;
	msg_flow[1] = offset;
	
	if((logMsgFlag & 0x04) || (logMsgFlag & 0x02) || shmp->process_info.logMsisdn)
	{  
		    DebugMsgDelimiter();
			DebugMsg(debugmib.display.asciiOut,
				"[%04d] did=%d, send open response result: %d! (%ld.%ld)",
					portid,did,result,tvnow.tv_sec,tvnow.tv_usec);	
	}	
	
	if(!map_send_comdata(msg_flow))
	{		
		return 0;		
	}
	return 1;
}

int pps_send_map_opr(struct MapOprData_struct *opr_ptr, int delimiter_flag)
{
	u_char	data_flow[256];
	u_short	data_len,portid;

	 _state_data    *shmp=(_state_data *)&smshm_ptr->state_data;

	PutLogFunID("pps_send_map_opr");

	map_opr_stof(opr_ptr,data_flow,0);
	data_len = data_flow[0]*256 + data_flow[1] + 2;
	if(delimiter_flag)
	    data_flow[data_len-1] = 0x10;
	else
	    data_flow[data_len-1] = 0x00;
	data_flow[data_len++] = 0x00; 
	data_flow[data_len++] = 0x00;
	data_flow[0] = (data_len - 2) >>8;
	data_flow[1] = (data_len - 2) & 0xff;

	portid = (data_flow[3]*256 + data_flow[4])%(MAX_FSM_PROCESS);
	shmp += portid;
	
	if((logMsgFlag == 0xff) || shmp->process_info.logMsisdn)
	{
		DebugMsg(debugmib.display.asciiOut,
				"portid: %d ,did: %d, Send Map Opr.  @ %ld.%ld",
				portid,shmp->context_info.map_did,
				tvnow.tv_sec,tvnow.tv_usec);
		pps_debug_map_msg(data_flow,1);		
	}
	
	
	return map_send_oprdata(data_flow);
}

int pps_send_mnp_ati(u_short portid)
{
	char	msisdn[32];
	char	data_flow[256];
	int		len;
	struct	MapOprData_struct opr_data;
	struct  MapOprSrv_struct  map_opr;
	struct	MapATI_Arg	*ati_arg;
	
	 _state_data    *shmp=(_state_data *)&smshm_ptr->state_data;

	PutLogFunID("pps_send_mnp_ati");
		
	shmp += portid;
	
	ati_arg = &map_opr.msg_list.ati_arg;
	ati_arg->param_flag = 0x07;
	ati_arg->sub_ident.choice_flag = 2;
	len = strlen((char *)shmp->called_info.number); /* can be caller */
	if(len>(ISDN_LEN-1)*2) len = (ISDN_LEN-1) * 2;
	ati_arg->sub_ident.choice.msisdn[0] = (len+1)/2+1;
	ati_arg->sub_ident.choice.msisdn[1] = 0x91;
	ppsAsciiToBcdR(&ati_arg->sub_ident.choice.msisdn[2],
			shmp->called_info.number,
			(len+1)/2*2);
	if(len %2)
	{
		ati_arg->sub_ident.choice.msisdn[(len+1)/2+1] |= 0xF0;
	}
	ati_arg->req_info.param_flag = 0x40;
	
	ppsBcdToAsciiR(msisdn,&ppsParam.ppsNumber[1],20);
	StringCut(msisdn,'F');	
	len = (strlen(msisdn)+1)/2;
	if(len>ISDN_LEN-1) len = ISDN_LEN-1;	
	ati_arg->scf_add[0] = len+1;
	ati_arg->scf_add[1] = 0x91;
	memcpy(&ati_arg->scf_add[2],&ppsParam.ppsNumber[1],len);
	
	shmp->context_info.map_iid = 
		map_get_invokeid(shmp->context_info.map_did);
	
	map_opr.port_id = portid;
	map_opr.dialogue_id = shmp->context_info.map_did;
	map_opr.invoke_id = shmp->context_info.map_iid;
	map_opr.message_type = AnyTimeInter;
	map_opr.message_flag = MAP_REQUEST;
	
	build_mapparam(&map_opr, (u8 *)data_flow);
	 
	opr_data.port_id = portid;
	opr_data.dialogue_id = map_opr.dialogue_id;
	opr_data.invoke_id = map_opr.invoke_id;
	opr_data.message_type = map_opr.message_type;
	opr_data.message_flag = map_opr.message_flag;
	opr_data.param_flag = 0x1f;
	len = build_mapparam(&map_opr,opr_data.param);
	if(len<=0 || len>MAX_MAPPOPR_LEN)
	{
		return 0;
	}
	opr_data.param_len = len;
	opr_data.param_flag |= 0x20;
	

	if((logMsgFlag == 0xff) || shmp->process_info.logMsisdn)
	{
			DebugMsg(debugmib.display.asciiOut,
				"portid: %d ,did: %d, Send Map ATI_Req.  @ %ld.%ld",
				portid,shmp->context_info.map_did,
				tvnow.tv_sec,tvnow.tv_usec);
			
	}		
	return pps_send_map_opr(&opr_data, 1);
}


int pps_send_routing_home_prn(u_short portid)
{
	char	msisdn[32],buf[32];
	//char	data_flow[256];
	int		len;
	struct	MapOprData_struct opr_data;
	struct  	MapOprSrv_struct  map_opr;
	struct	MapPRN_Arg	*prn_arg;
	
	 _state_data    *shmp=(_state_data *)&smshm_ptr->state_data;

	PutLogFunID("pps_send_routing_home_prn");
		
	shmp += portid;
	
	prn_arg = &map_opr.msg_list.prn_arg;
	prn_arg->param_flag = 0x07;
	memcpy(prn_arg->imsi, shmp->caller_info.IMSI, 8);

	//isdn_ston(msisdn, shmp->cdr_info.locationNumber);	
	isdn_ston((u8 *)msisdn, shmp->caller_info.number);	
	isdn_ntoa(prn_arg->msc_num, (u8 *)msisdn);
	
	ppsBcdToAsciiR(buf, shmp->cdr_info.called, 14);
	StringCut(buf, 'F');
	StringCut(buf, 'E');
	isdn_ston((u8 *)msisdn, (u8 *)buf);
	isdn_ntoa(prn_arg->msisdn, (u8 *)msisdn);

	
	shmp->context_info.map_iid = 
		map_get_invokeid(shmp->context_info.map_did);
	
	map_opr.port_id = portid;
	map_opr.dialogue_id = shmp->context_info.map_did;
	map_opr.invoke_id = shmp->context_info.map_iid;
	map_opr.message_type = ProvRoamNum;
	map_opr.message_flag = MAP_REQUEST;
	map_opr.version = 2;
	

	opr_data.port_id = portid;
	opr_data.dialogue_id = map_opr.dialogue_id;
	opr_data.invoke_id = map_opr.invoke_id;
	opr_data.message_type = map_opr.message_type;
	opr_data.message_flag = map_opr.message_flag;
	opr_data.param_flag = 0x1f;
	
	len = build_mapparam(&map_opr,opr_data.param);
	if(len<=0 || len>MAX_MAPPOPR_LEN)
	{
		return 0;
	}
	opr_data.param_len = len;
	opr_data.param_flag |= 0x20;
	

	if((logMsgFlag == 0xff) || shmp->process_info.logMsisdn)
	{
			DebugMsg(debugmib.display.asciiOut,
				"portid: %d ,did: %d, Send Map PRN_Req.  @ %ld.%ld",
				portid,shmp->context_info.map_did,
				tvnow.tv_sec,tvnow.tv_usec);
			
	}		
	return pps_send_map_opr(&opr_data, 1);
}


int pps_send_map_close(u_short portid)
{
	u_char	data_flow[256];
	
	_state_data    *shmp=(_state_data *)&smshm_ptr->state_data;

	PutLogFunID("pps_send_mnp_ati");
		
	shmp += portid;
	
	data_flow[0] = 0;
	data_flow[1] = 12;
	data_flow[2] = MAP_FLAG;
	data_flow[3] = portid>>8;
	data_flow[4] = portid & 0xff;
	data_flow[5] = 0;
	data_flow[6] = shmp->context_info.map_did >> 8;
	data_flow[7] = shmp->context_info.map_did & 0xff;
	data_flow[8] = 0x00;
	data_flow[9] = MAP_CLOSE;
	data_flow[10] = MAP_REQUEST;
	data_flow[11] = NormalRelease;
	data_flow[12] = 0x00;
	data_flow[13] = 0x00;
	//data_flow[1] = len;
	
	map_send_comdata(data_flow);
	
	if((logMsgFlag == 0xff) || shmp->process_info.logMsisdn)
	{
			DebugMsg(debugmib.display.asciiOut,
				"portid: %d ,did: %d, Send Map Close @ %ld.%ld",
				portid,shmp->context_info.map_did,
				tvnow.tv_sec,tvnow.tv_usec);
			pps_debug_map_msg(data_flow,1);
	}			
	return 1;
}

int pps_debug_map_msg(u_char *data_flow, int flag)
{
	int		len,loop;
	char	buf[1024],buf1[6];
	
	if(!flag)
	DebugMsg(debugmib.display.asciiOut,
		" \33[32m-- <P/DID=%04d/%04d> Rec. MSG <ocode: %d> @%ld.%ld\33[0m",
						data_flow[3]*256+data_flow[4],
						data_flow[6]*256+data_flow[7],
						data_flow[9],
						tvnow.tv_sec,tvnow.tv_usec);
	else
	DebugMsg(debugmib.display.asciiOut,
		" \33[32m-- <P/DID=%04d/%04d> Snd. MSG <ocode: %d> @%ld.%ld\33[0m",
						data_flow[3]*256+data_flow[4],
						data_flow[6]*256+data_flow[7],
						data_flow[9],
						tvnow.tv_sec,tvnow.tv_usec);
	len = data_flow[0] * 256 + data_flow[1];
	DebugMsg(debugmib.display.asciiOut,"------------ Message Flow ----------------");
	memset(buf,0,1024);
	for(loop=0;loop<len+2;loop++)
	{
		sprintf(buf1,"%02X ",data_flow[loop]);
		strcat(buf,buf1);
		if((loop+1)%16==0){
			sprintf(buf1,"\r\n");
			strcat(buf,buf1);
		}
	}
	DebugMsg(debugmib.display.asciiOut,"%s\r\n",buf);
	return 1;
}
