#include "datagram.h"
#include "newops.h"

/******************************************************************
* ListLength() does just what it says.  It takes the first datagramlist_t structure and 
* returns the length of the  entire list
* ****************************************************************/

int ListLength( datagramlist_t *dglist_t_p ) {
	int listlength=0; // Make sure we initialize the starting length to zero
	while( dglist_t_p != NULL ) { // While we have a valid list, increment the counter
		listlength++;
                dglist_t_p = dglist_t_p->nextlist_p; // Move to the next list
	}
	return listlength; //return the lengh (int)
}



/******************************************************************
* SortMessages() simply sorts the messages by message id.  This is slightly complicated
* because the message ids are stored in the datagram_t structure, not the datagramlist_t structure, so we
* need to hunt a little more to make a match, but it's not too bad.  It returns a pointer to the first
* datagramlist_t structure in the list.
* ****************************************************************/

datagramlist_t *SortMessages( datagramlist_t *dglist_t_p ) {
	int i, listlength = 0;
	datagramlist_t *current_p, *last_p;

	listlength = ListLength( dglist_t_p ); //Figure out the length of the list
	for ( i=1; i<= listlength -1; i++ ) { //Step through the list one by one
		//printf( "in look number %d\n\n", i );
		current_p = dglist_t_p;
		last_p = NULL;
	 	while( current_p->nextlist_p != NULL) {
			//printf( "comparing %d with %d\n\n", current_p->first_p->messageid, current_p->nextlist_p->first_p->messageid );
			if ( current_p->first_p->messageid > current_p->nextlist_p->first_p->messageid ) { 
				//If we're at the first term in the list, switch them and make recored the new beginning of the list
				if ( last_p == NULL ) { 
					//printf( "First item in the list\n\n" );
					//printf( "swapping %d with %d\n\n", current_p->first_p->messageid, current_p->nextlist_p->first_p->messageid );
					dglist_t_p = current_p->nextlist_p;		
					current_p->nextlist_p = current_p->nextlist_p->nextlist_p;
					dglist_t_p->nextlist_p = current_p;
					last_p = dglist_t_p;
				}
				//simply swap the two elements
				else { 
					//printf( "Not the last element in the list\n\n" );
					//printf( "swapping %d with %d\n\n", current_p->first_p->messageid, current_p->nextlist_p->first_p->messageid );
					last_p->nextlist_p = current_p->nextlist_p;
					current_p->nextlist_p = current_p->nextlist_p->nextlist_p;
					last_p->nextlist_p->nextlist_p = current_p;
					last_p = last_p->nextlist_p;
				}
			}
			//Walk through the list if there is no need to switch
			else {
				last_p = current_p;
				current_p = current_p->nextlist_p;
			}
		}
	}
	return dglist_t_p;
}



/******************************************************************
* SearchMessages() looks through all the datagrams and prints out any matches
* to a user input search string.  When a match is found, it prints out a message ID, 
* a datagram sequence number, and the actual message.  It returns nothing
* *****************************************************************/

void SearchMessages( datagramlist_t *dglist_t_p, char *searchstring ) {
	int found = 0;
	char *result;
	datagramlist_t *current_p;
	datagram_t *currentdg_p;
	current_p = dglist_t_p;
	while ( current_p != NULL ) { // We make sure we have a valid datagramlist_t pointer
		currentdg_p = current_p->first_p;
		while ( currentdg_p != NULL ) { // We make sure we have a valid datagram_t pointer
			result = strstr( currentdg_p->message, searchstring ); // We set up our search condition. 
			if ( result != NULL ) { //Since strstr() returns NULL if nothing is found, it it returns !NULL (actually a string) we have a match
				found = 1;
				printf( "\n\n#################################################################################\n" );
				    printf( "#                       Result found in message ID %d                          #\n", currentdg_p->messageid );
				printf( "#################################################################################\n" );
				printf ( "%d:\t%s", currentdg_p->sequence, currentdg_p->message );
			}
			currentdg_p = currentdg_p->next_p; //We move to the next datagram_t
		}
		current_p = current_p->nextlist_p; // We move to the next datagramlist_t
	}
	if ( found == 0 ) {
		printf( "\n\nNo matches to \"%s\" found\n\n", searchstring );
	}
	return; // We return nothing (null)
}



/******************************************************************
* DeletePartials() hunts through the datagramlist_t structures, compares
* the received number of datagrams with the expected number of datagrams
* and removes any datagramlist_t structures from the list that are not complete.
* This includes datagrams that still may exist in the data file.  It returns a pointer
* to the beginning of the datagramlist_t list
* ****************************************************************/

datagramlist_t *DeletePartials( datagramlist_t *dglist_t_p ) {
        datagramlist_t *current_p, *last_p;
	datagram_t *current_dg, *last_dg;
	int found = 0;
        last_p = NULL;
        current_p = dglist_t_p;
	if ( dglist_t_p != NULL ) { // Let's make sure our list passed into the function isn't NULL
		current_p = dglist_t_p;
		last_p = NULL;
		found = ( current_p->expected != current_p->received );
		while ( ( current_p->nextlist_p != NULL ) && ( !found ) ) { //While we're not at the end of the list and
			last_p = current_p;				    //we haven't found a match, keep looking
			current_p = current_p->nextlist_p;
			found = ( current_p->expected != current_p->received );
		}	
		if ( found ) { //Hooray, we found a match.  We need to get rid of it, but how???
			if ( last_p == NULL ) { // If it's the first item in the list, we make the start of the list the second list
				dglist_t_p = current_p->nextlist_p; 
			} else {
				last_p->nextlist_p = current_p->nextlist_p; 
				// Let's get rid of the individual datagrams and free up some memory
				current_dg = current_p->first_p;
				while( current_dg != NULL ) {
					last_dg = current_dg;
					current_dg = current_dg->next_p;
					free( last_dg );
				}

			}
			free( current_p ); // Here we free up the actual list
		} else {
			return dglist_t_p; // If we're here, then we're at the last item in the list and it's not a match
		}
		if ( dglist_t_p != NULL ) { //This will recursively call the function again if the starting list is not NULL
			dglist_t_p = DeletePartials( dglist_t_p ); //Probably not the most efficient, but effective.
		}						   //Why re-invent the wheel (or function).
	}
	return dglist_t_p; // Ahhh...  We return what we started out after.
}


