#include "fsm.h"
#include "converter.h"
/*=========================================================================
Function: CompleteGraph();
Comments: This function builds a complete graph of the service specification
	  provided, by introducing a dump state and then labelling all the
	  transitions to the dump state.
Inputs:   fsm_in - the state machine which needs to be completed.
	  fsm_out - the completed graph of the input state machine (result).
	  fp - the file pointer to the event set of the state machine.

Author:	  Sudhir Nelvagal. (Almost completely rewritten by Greg Stamp '04)
Advisor:  Dr. Ratnesh Kumar.
==========================================================================*/
void CompleteGraph(FILE *fp, FSM *fsm_in, FSM *fsm_out)
{
	FILE *fp_out;
	int i = 0; /* count integer */
	int num_states=0, new_num_trans=0, num_trans=0, num_events=0, trantodumpindex[MAX_LENGTH];
	ST_LIST *curr_state;
	TR_LIST *curr_trans, *begin_trans;
	char *eventlist[MAX_LENGTH];

	if(!fp)
		prog_abort("CompleteGraph: Invalid file pointer");
	if(!fsm_in)
		prog_abort("CompleteGraph: Null pointer passed for FSM *");
	if(!fsm_out)
		prog_abort("CompleteGraph: Null pointer passed for FSM *");

	/* Allocating memory for the variables */
	for(i = 0; i < MAX_LENGTH; i++)/*not exactly appropriate place for MAX_LENGTH*/
		eventlist[i] = (char *)calloc(sizeof(char), MAX_LENGTH);

	fp_out = fopen("tmp.out", "w+");	/* temp file to hold completed FSM */
	
	/* read the event set into a buffer */
	for(i = 0; fscanf(fp, "%s", eventlist[i]) == 1; i++);

	num_events = i;

	/* Get the number of states from the fsm */
	num_states = get_NStates(fsm_in);

	/* write the new num of states value to the output file */
	fprintf(fp_out, "%d\n\n", ++num_states); /* num_states + dump state */
	
	curr_state = NULL;
	curr_state = fsm_in->states;		/* point to initial state */
	curr_trans = fsm_in->states->trans; /* initial trans of initial state */
	
	while(curr_state) {				/* repeat until all states are  covered */
		begin_trans = curr_trans;	/* keep pointer to initial transition */
		num_trans = get_NTrans(curr_state);

		for(i = 0; i < num_events; i++)	/* initialize index values to 1 */
			trantodumpindex[i] = 1;

		/* if there is a transition in the eventlist, won't add this transition to dump state */
		while(curr_trans){				
			for(i = 0; i < num_events; i++){
				if(strcmp(curr_trans->input, eventlist[i]) == 0)
					trantodumpindex[i] = 0;
			}
			curr_trans = curr_trans->next; /* check next transition */
		}

		/* if transition in eventlist does not exist in this state, add a transition to dump */
		new_num_trans = num_trans;
		for(i = 0; i < num_events; i++){
			if(trantodumpindex[i])
				new_num_trans++;
		}

		/* write the new fsm state data to the temp file */
		fprintf(fp_out, "\n%s\t%d\t%d\n", curr_state->name,
				curr_state->marked, new_num_trans);

		/* The existing transitions are maintained as it is */
		while(begin_trans){
			fprintf(fp_out,"%s\t%s\n", begin_trans->input,
					begin_trans->next_state->name);
			begin_trans = begin_trans->next;
		}

		/* Write new transitions to dump in temp file */
		for(i = 0; i < num_events; i++) {
			if(trantodumpindex[i])
				fprintf(fp_out, "%s\t%s\n", eventlist[i],"dump");
		} 
		
		curr_state = curr_state->next; /* point to next state */ 

		/* reinitialize trans ptr to point to next state's transition 
		as long as all the states are not covered */
		if(curr_state)
			curr_trans = curr_state->trans;
	} 
	
	/* The dump state has to be added to the fsm */
	fprintf(fp_out, "\n%s\t%d\t%d\n", "dump", MKD, num_events);

	/* The dump state contains all the transitions defined in the event set
	   to itself */
	for(i=0 ; i < num_events; i++)
		fprintf(fp_out, "%s\t%s\n", eventlist[i], "dump");

	/* read the result into the fsm_out structure */
	rewind(fp_out);
	fsm_read(fp_out, fsm_out);
	fclose(fp_out);
	unlink("tmp.out");

	rewind(fp);
	for(i=0;i<MAX_LENGTH;i++)
		free(eventlist[i]);

}	/* complete_graph ends*/
