#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

struct translation_structure{
        unsigned char series[155];   
	long unsigned int times;
	long unsigned int len;
}table[39679];





int match_search(int num1, unsigned char *linestring){
	//returns 0 for match found and written
	//returns 1 for no matches found                                
	int num4;
	int num5;
	int num3;

	for(num4=0; num4<39679; num4++){
		if(table[num4].times>0){
			//if(strcmp(table[num4].series, linestring) == 0){
			if(table[num4].len == num1){
				num5=0;
				for(num3=0; num3<num1; num3++){
					if(table[num4].series[num3] != linestring[num3]){
						num5=1;
						num3=num1;
						//return(1);
					}
				}
				//matched
				if(num5==0){
					table[num4].times++;
					//num4=39679;
					return(0);
				}
			}
		}
	}
	return (1);
}


int empty_search(int num1, unsigned char *linestring){
	//return 0 if empty spot found and wrote to
	//return 1 if no empty spots found

	int num3;
	int num4;                        
	int num5=0;

	for(num4=0; num4<39679; num4++){
        	if(table[num4].times==0){
			//array is not full
			//num4 here is where you write it to
			for(num3=0; num3<num1; num3++){
				table[num4].series[num3]=linestring[num3];
			}
			table[num4].times=1;                                                
			table[num4].len = num1;
			return(0);
                                                
			//num5=1;                                                
			//num4=39679;
		}
	}
	return(1);
}




int full_search(int num1, unsigned char *linestring){
	//return 0 for found and replaced array string of 1x
	//return 1 for error (no 1x strings found, for now)
	int num4, num3; 

	for(num4=0; num4<39679; num4++){
		if(table[num4].times==1){
			//replace it                                                                                                       
			for(num3=0; num3<num1; num3++){                                                                
				table[num4].series[num3]=linestring[num3];                        
			}              
			table[num4].times=1;                                         
			table[num4].len = num1;
         		return(0);
		}
	}
	return(1);
}





/*

table[0].series=(char *)malloc(sizeof(char)*whatever);
={
    {(char[]){0, 1, 2}, 5, 100, 3},
    {(char[]){4, 5, 6, 7}, 1, 2, 4},
    {(char[]){0, 1, 2}, 5, 100, 3},   
    {(char[]){4, 5, 6, 7}, 1, 2, 4},
    {(char[]){0, 1, 2}, 5, 100, 3},
    {(char[]){4, 5, 6, 7}, 1, 2, 4}
};
*/


void usage(void){
        printf("\tUsage: patterns [output] [input] [min pattern size (bytes)]\n");
        exit(1);
}


int main(int argc, char **argv){
        FILE *output;
        FILE *input;
	unsigned char *mem_file;
	int pat_size;
	int file_bytes=0;
	unsigned char *linestring;
	int character;
	int num1, num2, num3, num4, num5;
	double progress=0;
	int max_searchs=0;
	int half_file;
	int return_val;	

        if(argc != 4){
                usage();
	}

	for(num4=0; num4<39679; num4++){  
		table[num4].times = 0;
		table[num4].len = 0;                
	}


	pat_size = atoi(argv[3]);
	//linestring = (char *)malloc(sizeof(char)*pat_size);

        if( ( input = fopen( argv[2], "r" ) ) == NULL ) {
                fprintf( stderr, "Error opening %s\n", argv[2] );
                exit( 1 );
        }
        if( ( output = fopen( argv[1], "w" ) ) == NULL ) {
                fprintf( stderr, "Error opening %s\n", argv[1] );
                exit( 1 );
        }                   

	//start in 0 upto half the bytes of file or EOF
        //while( fgets(linestring, sizeof(linestring), input) != NULL)
        //{
	


	character=getc(input);
	while(character != EOF){			
		file_bytes++;
		character=getc(input);
	}
	
	mem_file = (unsigned char *)malloc(sizeof(unsigned char)*file_bytes);

	fseek ( input , 0 , SEEK_SET );
	num1=0;
        for(character=getc(input); character != EOF; num1++ ){
        	mem_file[num1]=character;
		character=getc(input);        
        }


	fclose(input);

        printf("input: %s\n", argv[2]);
        printf("output: %s\n", argv[1]);
        printf("pat_size: %d\n", pat_size);
        printf("bytes: %d\n", file_bytes);

	half_file = sizeof(unsigned char)*ceil(file_bytes/2);
	linestring = (unsigned char *)malloc(half_file);

	printf("linestring size: %d bytes\n", half_file);

	for(num1=pat_size; num1<file_bytes/2; num1++){
		max_searchs++;
	}

	printf("max_searchs: %d\n", max_searchs);

	//sleep(2);

	for(num1=pat_size; num1<(file_bytes/2); num1++){
		//system("clear");
		printf("progress: %.02lf%%\n", (progress/max_searchs)*100 );
		progress++;
		//sleep(1);

		//linestring = (unsigned char *)malloc(sizeof(unsigned char)*num1);
		//memset ((void*) linestring, '\0', sizeof (linestring));

		//start position in mem array
		for(num2=0; num2<(file_bytes-pat_size); num2++){
			//fseek ( input , num2 , SEEK_SET );
			//start_b = num2;
			
			//character=getc(input);
			
			//strcpy(linestring, &character);


			//upto pat_size from start position
			for(num3=0; num3<num1; num3++){
				//character=getc(input);
				//character=mem_file[num2+num3];
				//strcat(linestring, &character);
				//linestring[num3]=character;
				linestring[num3]=mem_file[num2+num3];

				//if(character == EOF){
				//}
					
			}



			//you have string here
			//save it to array of strings
				//check if already in array, if it is then increment counter
				//if it isn't, check if array is full, 
					//if it is then ... replace first 1 count string found
					//if it isn't then add string with 1 count


			return_val = match_search(num1, &linestring);


/*
			for(num4=0; num4<39679; num4++){
				if(table[num4].times>0){
					//if(strcmp(table[num4].series, linestring) == 0){
					if(table[num4].len == num1){
						num5=0;
						for(num3=0; num3<num1; num3++){
							if(table[num4].series[num3] != linestring[num3]){
								//table[num4].times++;
								//num4=39679;
								//num5++;
						
								num5=1;
							}
						}
						//matched
						if(num5==0){
							table[num4].times++;
							num4=39679;
						}
					}
				}
			}

*/

if(return_val==1){
	return_val=empty_search(num1, &linestring);
}

/*
			//means it wasn't found
			if(num4!=39680){
				num5=0;
				for(num4=0; num4<39679; num4++){				
					if(table[num4].times==0){
						//array is not full
						//num4 here is where you write it to
						//table[num4].series=(unsigned char *)malloc(sizeof(unsigned char)*num1);
						//memset ((void*) table[num4].series, '\0', sizeof (table[num4].series));
						//strcpy(table[num4].series, linestring);
						for(num3=0; num3<num1; num3++){
							table[num4].series[num3]=linestring[num3];
						}
						table[num4].times=1;
						table[num4].len = num1;
						num5=1;
						num4=39679;
					}
					//if(table[num4].times==1 && num5 != 1){
						
					//}
				}
*/


if(return_val==1){
        return_val=full_search(num1, &linestring);
}

if(return_val==1){
	printf("error!\n");
	exit(1);
}

/*

				if(num5 == 0){
					//array is full
					for(num4=0; num4<39679; num4++){
						if(table[num4].times==1){
							//replace it
							//table[num4].series=(unsigned char *)malloc(sizeof(unsigned char)*num1);
							//memset ((void*) table[num4].series, '\0', sizeof (table[num4].series));
							//strcpy(table[num4].series, linestring);

							for(num3=0; num3<num1; num3++){
								table[num4].series[num3]=linestring[num3];
							}
							table[num4].times=1;
							table[num4].len = num1;
							num4=39679;
						}
					}
				}	
			}
*/









		}
		

	}
/*
	printf("input: %s\n", argv[2]);
	printf("output: %s\n", argv[3]);
	printf("pat_size: %d\n", pat_size);
	printf("bytes: %lu\n", file_bytes);
	printf("first char: %c\n", character);
*/


	//parse structure and write to output 
	for(num4=0; num4<39679; num4++){
        	if(table[num4].times >= 4){
			for(num3=0; num3<table[num4].len; num3++){
				fprintf(output, "%c ", table[num4].series[num3]);
			}
			fprintf(output, "%lu %lu\n", table[num4].len, table[num4].times);
		}
        }




	//fclose(input);
	fclose(output);
return 0;
}

/*
output:
	x unique strings of atleast pat_size length
	10 most common:
	1). bla z
	2). foo z
	3). foobla z
	4). blafoo z
	.
	.
save to output.txt upto 39680 most common strings ordered by z

*/
