#include "fsm.h"
#include "converter.h"

/*=========================================================================== 
Function: AugmentFSM
Comments: This function augments a NFSM without epsilon moves so that a 
	  strict synchronous composition can be done using the existing library
	  routine. It is assumed that the user has already input the event
	  set with which the fsm is to be augmented.
Inputs:	  fp - file pointer to the file containing the augmentation event set.
	  fsm_pr - pointer to the fsm which needs to be augmented.
Note:	  The augmentation events and the events in the fsm which needs augment
	  ation must be exclusive and distinct.
Author:	  Sudhir Nelvagal
Advisor:  Dr. Ratnesh Kumar
============================================================================*/
void AugmentFsm(FILE *fp, FSM *fsm_pr)
{
	FILE *fp_out, *fp_fsm;
	int i=0,j=0,k=0,p=0,num_tran,num_aug,num_event,no_states;
	char *augevent[MAX_LENGTH], *tempevent[MAX_LENGTH], *temp[MAX_LENGTH];
	ST_LIST *curr_stat;
	TR_LIST *curr_tran;

	if(!fp)
		prog_abort("AugmentFsm: Invalid file pointer");
	if(!fsm_pr)
		prog_abort("AugmentFsm: Null value passed as arg for FSM*");

	for(i=0;i<MAX_LENGTH;i++) {/*not best use of MAX_LENGTH*/
		augevent[i] = (char *)calloc(sizeof(char), MAX_LENGTH);
		temp[i] = (char *)calloc(sizeof(char), MAX_LENGTH);
		tempevent[i] = (char *)calloc(sizeof(char), MAX_LENGTH);
	}

	if((fp_out = fopen("fsm.tmp", "w+"))==NULL) {
		perror("fsm.tmp");
		exit(1);
	}

	no_states = get_NStates(fsm_pr); /* # of states in the fsm */
	fprintf(fp_out, "%d\n", no_states);	
	fflush(fp_out);
	i=0;
	while(fscanf(fp, "%s", temp[i])==1) {
		strcpy(tempevent[i], temp[i]);	
		strcpy(augevent[i], temp[i]);
		i++;
	}
	num_event = i;	/* num of events in the list */
	
	curr_stat = fsm_pr->states; /* point to the initial state */
	curr_tran = fsm_pr->states->trans; /* initial trans of initial state */
	while(curr_stat) {
		num_tran = get_NTrans(curr_stat); /* num of transitions */
		
		/*Write the  data to a tmp file */
		fprintf(fp_out, "\n%s\t%d\t%d\n", curr_stat->name,
				curr_stat->marked, num_event+num_tran);

		/* obtain all transitions at each state */	
		i=0,j=k=num_event;	/* init the variables */
		while(num_tran) {  /* until all transitions are covered */
			/* The existing transitions are maintained */
				fprintf(fp_out,"%s\t%s\n",curr_tran->input,
				curr_tran->next_state->name);
		
			/* The list of events in the augevent list are the 
			actual set of events on which each state is augmented.
			so include these events */

			/* Now search thru the augevent set to find if the 
			current transition label matches any of the events
			in the augevent set.  If a match is found, remove the
			transition from the augevent set, else continue.
			When all the transitions are stepped thru', a list
			of events, are obtained.  These events are the events
			which are augmented at that state by adding a self loop
			with the events as transition labels */
			while(num_event) {
				if(strcmp(curr_tran->input,
					augevent[k-num_event])==0) {
					; num_event--;
				}
				else {
					strcpy(augevent[i],augevent[k-num_event]); /*Greg changed*/
					num_event--;
					i++;
				}
			}
			*augevent[i]='\0'; /* important to pad a null Greg Changed*/
			curr_tran = curr_tran->next; /* point to next tran */
			/* num of events is the size of the array augevent */
			num_event = k=i;
			i=0; /* reset i to zero */
			num_tran--;
		}	
		/* Now write this augmented trans to the FSM */
		for(p=0;p<num_event;p++) {
			fprintf(fp_out, "%s\t%s\n", augevent[p], curr_stat->name);
		}
		/* The list of events in the augevent list are the 
		actual set of events on which each state is augmented.
		so include these events */
		
		curr_stat = curr_stat->next; /* point to the next state */
		num_event=j;
		i=0;
		
		/* copy the original list of events back to the augevent list, and original eventtypes*/
		for(i=0;i<num_event;i++) {
			strcpy(augevent[i],tempevent[i]); /*greg changed*/
		}
		i=0;
		
		/* reinitialize trans ptr to point to next state's transition
		as long as all the states are not covered */
		if(curr_stat) {
			curr_tran = curr_stat ->trans;
		}
	}		
	/* close the file after writing */
	fflush(fp_out);
	fclose(fp_out);	
	/* Now read the data written in "fsm.tmp" into an FSM structure */
	if((fp_fsm = fopen("fsm.tmp", "r"))==NULL) {
		perror("File Open");
		exit(1);
	}
	/* read it into the fsm structure pointer, which was passed to
	this function so that compose.c can use it in its program if needed */
	fsm_read(fp_fsm, fsm_pr);

	for(i=0;i<MAX_LENGTH;i++) {
		free(temp[i]);
		free(augevent[i]);
		free(tempevent[i]);

	}
	fclose(fp_fsm);
	unlink("fsm.tmp");
	rewind(fp);


} /* AugmentFsm ends */
