#include "./include/mtp3.h"
#include "./include/mtpstm.h"
#include "./include/mtpext.h"
#include "./include/mtpfunc.h"

/*@ignore@*/
void hmrt_srm_msg(WORD linkset, BYTE MsgType, long dst);
void hmrt_tfrc_update_routing_tables(WORD dst, BYTE nw);
void tsrc_fun6(WORD link,BYTE nw,WORD sp_place);
void tsrc_fun8(WORD ls,BYTE nw,WORD sp_place);
int	find_dst_place(long	dst,WORD ls);

void mark_alternative_linkset_available(BYTE *routine)
{
	(*routine) = ( (*routine) & 0xc3 ) + 0x10;/* mark alternative route use and acessible*/
}

void mark_alternative_linkset_unavailable(BYTE *routine)
{
	(*routine) = ((*routine) & 0xf3 ) + 0x08;/* mark alternative route can't use */
}

void mark_normal_linkset_available(BYTE *routine)
{
	(*routine) = ((*routine) & 0xcc) + 0x10;/* mark normal route can use,and acessible */
}

void mark_normal_linkset_unavailable(BYTE *routine)
{
	(*routine) = ((*routine) & 0xfc) + 0x02;/* mark normal route unavailable */
}

void mark_dstSP_inaccessible(BYTE *routine)
{
	(*routine) = ((*routine) & 0xcf);/* mark destination sp inaccessible */
}

int find_directLS_to_dst(long dst)
{
	int		i;
	
	for ( i=0; i<MAX_LS; i++ )
	{
		if ( mtp3_para->ls_pro[i].ls_op_pc == dst )
			return i;
	}
	return MAX_LS;
}

void tsrc_rtpc_signalling_route_unavailable(WORD dst, BYTE nw)
{
	WORD	ls;
	network	*sp;
	BYTE	msgopc;
	WORD	nls;
	WORD	als;
	
	nls = mtp3_para->nw[nw].routing[dst].normal_ls;
	als = mtp3_para->nw[nw].routing[dst].alternative_ls;
	sp = &mtp3.nw[nw];
	msgopc = TFPmsg_OPC;
	ls = mtp3_para->lk[TFPmsg_SrcLk].e1_to_linkset;

	if ( ls >= MAX_LS )//???
		return;
	if ( mtp3.ls[ls].adjacentsp_restarting == 1 )/* adjacent sp restarting */
	{
		if (nls == ls)
			mark_normal_linkset_unavailable(&sp->routine[dst]);
		else if (als == ls)
			mark_alternative_linkset_unavailable(&sp->routine[dst]);
	}
	else
	{
		if ( nls == ls )
		{
			if ( (sp->routine[dst] >> 6) == 2 )
				return;
			tsrc_fun6(TFPmsg_SrcLk,nw,dst);
			hmrt_tfrc_update_routing_tables(dst,nw);
		}
		else if ( als == ls )
		{
			tsrc_fun6(TFPmsg_SrcLk,nw,dst);
			hmrt_tfrc_update_routing_tables(dst,nw);
		}
	}
}

void tsrc_rtac_signalling_route_available(WORD dst, BYTE nw)
{
	int			ls;
	network		*sp;
	ulong		msgopc;
	WORD		nls_t;
	WORD	als_t;
	BYTE		current_route;
	WORD		msgopc_place;
	int			lsnoRSP_is_msgOPC;

	sp = &mtp3.nw[nw];
	current_route = sp->routine[dst] >> 6;
	msgopc = TFAmsg_OPC;
	ls = mtp3_para->lk[TFAmsg_SrcLk].e1_to_linkset;
	if ( ls >= MAX_LS )
		return;
	lsnoRSP_is_msgOPC = find_directLS_to_dst(msgopc);
	if ( lsnoRSP_is_msgOPC == MAX_LS )
		return;/* msg opc is not any linkset's remote sp */
	msgopc_place = mtp3.ls[lsnoRSP_is_msgOPC].adjacent_sp_place;
	if (msgopc_place > MAX_ROUTE)
		return;
	
	if ( !own_sp_restarting )
	{	
		if ( ((sp->routine[msgopc_place] >> 4) & 3) == SP_ACCESSIBLE )/* msg opc accessible */
			tsrc_fun8(ls,nw,dst);

		else/* msg opc inacessible */
		{
//			mtp3_debug(MTP3_DEBUG_LOG,"msgopc inacessible\n\r");
			sp->rtac_input[msgopc_place] = RTAC_DEST_ACCESSIBLE;/* send tfa to all adjacent sp */

			nls_t = mtp3_para->nw[nw].routing[msgopc_place].normal_ls;
			als_t = mtp3_para->nw[nw].routing[msgopc_place].alternative_ls;
			mtp3ObjInput.taprc_input[lsnoRSP_is_msgOPC] = TPRC_ADJACENT_SP_RESTARTING;

			if ( nls_t == ls )
				mark_normal_linkset_available(&sp->routine[msgopc_place]);
			else if ( als_t == ls )
				mark_alternative_linkset_available(&sp->routine[msgopc_place]);
			current_measure->ls_measure[ls][4]++;/* Broadcast TFA for recovery of measured linkset */
		}
	}
	hmrt_tfrc_update_routing_tables(msgopc_place,nw);
	hmrt_tfrc_update_routing_tables(dst,nw);
}

void rtpc_proc(BYTE netw,WORD dst)
{
	network	*nw;
	WORD	ls;
	
	nw = &mtp3.nw[netw];
	switch ( nw->rtpc_state[dst] )
	{
		case RTPC_IDLE_STATE:
			switch ( nw->rtpc_input[dst] )
			{
				case RTPC_RSRT_SEND_TFP_MSG:/* not supported */
					nw->rtpc_input[dst] = IDLE;
					hmrt_srm_msg(sdTFP_Ls,SIGNAL_TFP,mtp3_para->nw[netw].routing[dst].dpc);
					nw->rtpc_state[dst] = RTPC_WAIT_STATE;
				break;
		
				case RTPC_TSRC_SEND_TFP_MSG:/* send tfp message to linkset opposit sp */
//					printf("send tfp message to linkset %d,TFDPC=%lx\n",sdTFP_Ls,mtp3_para->nw[netw].dpc[dst]);
					nw->rtpc_input[dst] = IDLE;
					hmrt_srm_msg(sdTFP_Ls,SIGNAL_TFP,mtp3_para->nw[netw].routing[dst].dpc);
					nw->rtpc_state[dst] = RTPC_WAIT_STATE;
				break;

				case RTPC_DEST_INACCESSIBLE:/*one dst inaccessible, send tfp to all adjacent sp about this dst */
					nw->rtpc_input[dst] = IDLE;
					for ( ls=0; ls<MAX_LS; ls++ )
					{
						if ((mtp3_para->ls_pro[ls].nw_id) == netw)
						{
//							printf("send tfp message to linkset %d,TFDPC=%lx\n",ls,mtp3_para->nw[netw].dpc[dst]);
							hmrt_srm_msg(ls,SIGNAL_TFP,mtp3_para->nw[netw].routing[dst].dpc);/* send tfp to adjacent sp */
						}
					}
					if (own_sp_restarting == 1)
					{
//						hmrt_tra_msg(ls);//printf("send tra\n");
						mtp3ObjInput.tprc_input = TPRC_RTPC_TFP_SENT;
					}
				break;
		
				case RTPC_TFP_MSG:/* receive TFP from other sp */
//					printf("rtpc dst %d tfp\n",dst);
					nw->rtpc_input[dst] = IDLE;
					if ( controlled_rerouting_in_progress[dst] == TRUE )
						transfer_prohibited[dst] = TRUE;
					else
					{
						tsrc_rtpc_signalling_route_unavailable(dst,netw);
						if (!own_sp_restarting)
						{
							nw->rsrt_input[dst] = RSRT_RTPC_ROUTE_SET_TEST;
						}
						//if sp isn't restarting
						//start route set test
					}
				break;
		
				case RTPC_CTRL_RERT_TERMINATED:/* not supported */
					nw->rtpc_input[dst] = IDLE;
					controlled_rerouting_in_progress[dst] = FALSE;
					if ( transfer_prohibited[dst] == TRUE )
					{
						transfer_prohibited[dst] = FALSE;
						//tsrc_rtpc_signalling_route_unavailable
						//if sp isn't restarting
						//start route set test
					}
				break;
		
				case RTPC_CONTROLLED_RERT:/* not supported */
					nw->rtpc_input[dst] = IDLE;
					controlled_rerouting_in_progress[dst] = TRUE;
				break;
		
				case RTPC_RESTART_BEGINS:
					nw->rtpc_input[dst] = IDLE;
					controlled_rerouting_in_progress[dst] = FALSE;
					transfer_prohibited[dst] = FALSE;
					/* mark sp restarting */
				break;
		
				case RTPC_RESTART_ENDS:
					nw->rtpc_input[dst] = IDLE;
					/* cancel sp restarting */
				break;
			}
		break;
		
		case RTPC_WAIT_STATE:
			nw->rtpc_state[dst] = RTPC_IDLE_STATE;
		break;
	}
}

void rtac_proc(BYTE netw,WORD dst)
{
	network	*nw;
	WORD	ls;
	
	nw = &mtp3.nw[netw];
	switch ( nw->rtac_input[dst] )
	{
		case RTAC_TFA_MSG:
			nw->rtac_input[dst] = IDLE;
			tsrc_rtac_signalling_route_available(dst,netw);
			nw->rsrt_input[dst] = RSRT_RTAC_ROUTE_AVAILABLE;
		break;
		
		case RTAC_DEST_ACCESSIBLE:// one dst become accessible, send tfa to all adjacent sp about this dst
			nw->rtac_input[dst] = IDLE;
			for ( ls=0; ls<MAX_LS; ls++ )
			{
				if ( mtp3_para->ls_pro[ls].nw_id == netw)
				{
					hmrt_srm_msg(ls,SIGNAL_TFA,mtp3_para->nw[netw].routing[dst].dpc);/* send tfa to adjacent sp */
				}
			}
		break;
		
		case RTAC_STP_NOLONGER_FOR_DEST:
			nw->rtac_input[dst] = IDLE;
			hmrt_srm_msg(sdTFA_Ls,SIGNAL_TFA,mtp3_para->nw[netw].routing[dst].dpc);
		break;
		
		case RTAC_SEND_TFA_MSG:
			nw->rtac_input[dst] = IDLE;
			hmrt_srm_msg(sdTFA_Ls,SIGNAL_TFA,mtp3_para->nw[netw].routing[dst].dpc);
		break;
		
		case RTAC_FORCED_RERT:
		break;

		case RTAC_FORCED_RERT_TERMINATED:
		break;
		
		case RTAC_FORCED_RERT_NOT_REQ:
		break;
		
		case RTAC_RESTART_BEGINS:
		break;
		
		case RTAC_RESTART_ENDS:
		break;
	}
}

void rsrt_proc(BYTE netw,WORD dst)
{
	network	*nw;
	
	nw = &mtp3.nw[netw];
	switch (nw->rsrt_state[dst])
	{
		case RSRT_IDLE_STATE:
			switch (nw->rsrt_input[dst])
			{
				case RSRT_RTPC_ROUTE_SET_TEST:
					nw->rsrt_t10[dst] = 0;
					nw->rsrt_state[dst] = RSRT_WAIT_STATE;
					break;
				case RSRT_TSRC_ROUTE_SET_TEST:
					hmrt_srm_msg(mtp3_para->nw[netw].routing[dst].normal_ls,SIGNAL_RST,mtp3_para->nw[netw].routing[dst].dpc);					
					break;
				default:
					break;
			}
			break;
		case RSRT_WAIT_STATE:
			nw->rsrt_t10[dst] ++;
			switch (nw->rsrt_input[dst])
			{
				case RSRT_RTPC_ROUTE_SET_TEST:
					break;
				case RSRT_TSRC_ROUTE_SET_TEST:
					break;
				case RSRT_RTAC_ROUTE_AVAILABLE:
					nw->rsrt_t10[dst] = 0;
					nw->rsrt_state[dst] = RSRT_IDLE_STATE;
					break;
				default:
					break;
			}
			if (nw->rsrt_t10[dst] >= mtp3_para->mtp3_t10)
			{
				hmrt_srm_msg(mtp3_para->nw[netw].routing[dst].normal_ls,SIGNAL_RST,mtp3_para->nw[netw].routing[dst].dpc);
				//send route test message out
				nw->rsrt_t10[dst] = 0;
			}
			break;
		default:
			break;
	
	}
	nw->rsrt_input[dst] = IDLE;
}
/*@end@*/

