#include "fep.h"
#include "hexdump.c"

/* The following get_*_text functions are helper functions used to
   get enum type names as strings */
const char* get_polltype_text(enum polltype ptype)
{
	switch(ptype)
	{
		case POLL:
			return "POLL";
		case COMMAND:
			return "COMMAND";
		case TIMESYNC:
			return "TIMESYNC";
		default:
			return "UNKNOWN";
	}	
}

const char* get_status_text(enum errorstatus estat)
{
	switch(estat)
	{ case FEP_OK: 
			return "FEP_OK";
		case FEP_OUTOFRANGE: 
			return "FEP_OUTOFRANGE";
		case FEP_BADHANDLE: 
			return "FEP_BADHANDLE";
		case FEP_NOREPLY: 
			return "FEP_NOREPLY";
		case FEP_SCHBUSY: 
			return "FEP_SCHBUSY";
		case FEP_LINEBUSY: 
			return "FEP_LINEBUSY";
		case FEP_REPORTBUSY: 
			return "FEP_REPORTBUSY";
		case FEP_NOREPORT: 
			return "FEP_NOREPORT";
		case FEP_NOMEMORY: 
			return "FEP_NOMEMORY";
		case FEP_BADTIME: 
			return "FEP_BADTIME";
		case FEP_BADTIMESYNCH: 
			return "FEP_BADTIMESYNCH";
		case FEP_BADKIND: 
			return "FEP_BADKIND";
		case FEP_BADCONNECT: 
			return "FEP_BADCONNECT";
		case FEP_NOAUTHORITY: 
			return "FEP_NOAUTHORITY";
		default: 
			return "UNKNOWN";
	}
} 

const char* get_answererror_text(enum answererror err)
{
	switch(err)
	{
		case ERR_BSCF_ERR:
			return "ERR_BSCF_ERR";
		case ERR_NONE:
			return "ERR_NONE";
		case ERR_MSG_LEN:
			return "ERR_MSG_LEN";
		case ERR_MSG_HDR:
			return "ERR_MSG_HDR";
		case ERR_MSG_CHKSUM:
			return "ERR_MSG_CHKSUM";
		case ERR_MSG_TRAILER:
			return "ERR_MSG_TRAILER";
		default:
			return "UNKNOWN";
	}
}

const char * get_pollingfsm_text(enum Polling_FSM_States state)
{
	switch(state)
	{
		case INITSTATE:
			return "INITSTATE";
		case WRALARMSTATE:
			return "WRALARMSTATE";
		case CLRSTATE:
			return "CLRSTATE";
		case RTSONSTATE:
			return "RTSONSTATE";
		case CTSSTATE:
			return "CTSSTATE";
		case WRITESTATE:
			return "WRITESTATE";
		case RTSOFFSTATE:
			return "RTSOFFSTATE";
		case RDALARMSTATE:
			return "RDALARMSTATE";
		case RDSTATE:
			return "RDSTATE";
		case DONESTATE:
			return "DONESTATE";
		default:
			return "UNKNOWN";
	}
}

const char *get_replystatus_text(enum replystatus status)
{
	switch(status)
	{
		case FAILURE:
			return "FAILURE";
		case DONE:
			return "DONE";
		case UNUSED:
			return "UNUSED";
		default:
			return "UNKNOWN";
	}
}

const char *get_replykind_text(enum replykind kind)
{
	switch(kind)
	{
		case POLLREPLY:
			return "POLLREPLY";
		case SCHEDNEW:
			return "SCHEDNEW";
		case SCHEDDONE:
			return "SCHEDDONE";
		default:
			return "UNKNOWN";
	}
}

/* The following functions are used to print fep_reply, reply_ret structs and associated structs */
void print_fep_pollerror(fep_pollerror pollerror)
{
	printf("\t\t\t\t\t\tpoll error:\n");
	printf("\t\t\t\t\t\tanswererror msgerror:\t%s\n", get_answererror_text(pollerror.msgerror));
	printf("\t\t\t\t\t\tPolling_FSM_States state:\t%s\n", get_pollingfsm_text(pollerror.state));
	printf("\t\t\t\t\t\t\tint perrno:\t%d\n", pollerror.perrno);
	printf("\t\t\t\t\t\t\tint termination:\t%d\n", pollerror.termination);
	printf("\t\t\t\t\t\t\tint count:\t%d\n", pollerror.count);
}

void print_fep_answer_info(fep_answer_info info)
{
	printf("\t\t\t\t\tfep_answer_info:\n");
	printf("\t\t\t\t\t\tlong poll_time:\t%ld\n", info.poll_time);
	printf("\t\t\t\t\t\treplystatus status:\t%s\n", get_replystatus_text(info.status));
	printf("\t\t\t\t\t\tint poll_user_info1:\t%d\n", info.poll_user_info1);
	printf("\t\t\t\t\t\tint poll_user_info2:\t%d\n", info.poll_user_info2);
	printf("\t\t\t\t\t\tint retries:\t%d\n", info.retries);
	printf("\t\t\t\t\t\tint poll_error_count:\t%d\n", info.poll_error_count);
	for(int i = 0; i < info.poll_error_count; i++)
	{
		print_fep_pollerror(*info.pollerror);
	}
}

void print_fep_answer_short_msg(fep_answer_short_msg msg)
{
	printf("\t\t\t\t\tfep_answer_short:\n");
	printf("\t\t\t\t\t\tint message_len:\t%d\n", msg.message_len);
	printf("\t\t\t\t\t\tmessage:\t");
	for(int i = 0; i < msg.message_len; i++)
	{
		printf("%04x ", msg.message[i]);
	}
	printf("\n");
}

void print_fep_shortanswer(fep_shortanswer answer)
{
	printf("\t\t\t\tfep_shortanswer:\n");
	print_fep_answer_info(answer.info);
	print_fep_answer_short_msg(answer.msg);
}

void print_fep_shortanswer_list(fep_shortanswer_list answer_list)
{
	printf("\t\t\tfep_shortanswer_list:\n");
	printf("\t\t\t\tcount:\t%d\n", answer_list.count);
	for(int i = 0; i < answer_list.count; i++)
	{	
		print_fep_shortanswer(answer_list.answers[i]);	
	}
}

void print_fep_answer_list(fep_answer_list answers)
{
	printf("\t\tfep_answer_list:\n");
	printf("\t\t\tint size:\t%d\n", answers.size);
	print_fep_shortanswer_list(answers.fep_answer_list_u.shortp);
}

void print_fep_reply(fep_reply reply)
{
	printf("\tfep_reply: \n");
	printf("\t\tint reply:\t%d\n", reply.reply);
	printf("\t\tint schedule:\t%d\n", reply.schedule); 
	printf("\t\tint lineinfo:\t%d\n", reply.lineinfo);
	printf("\t\tpolltype kind:\t%s\n", get_polltype_text(reply.kind));
	printf("\t\treplykind flag:\t%s\n", get_replykind_text(reply.flag));
	printf("\t\tint schedule_sequence:\t%d\n", reply.schedule_sequence);
	printf("\t\tint global_sequence:\t%d\n", reply.global_sequence);
	printf("\t\tlong schedule_time:\t%ld\n", reply.schedule_time);
	printf("\t\tint user_info1:\t%d\n", reply.user_info1);
	printf("\t\tint user_info2:\t%d\n", reply.user_info2);
	print_fep_answer_list(reply.answers);
}

/* Dumps the ATMS's response to RPC Call (struct reply_ret) */
void print_reply_ret(reply_ret response) {
	printf("reply_ret:\n");
	// Print response status
	printf("\tfep_status: %s\n", get_status_text(response.status));
	print_fep_reply(response.reply_ret_u.info);
}
