#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
//two chars
char hexConverter( char a[2] )
{
	
	char total = 0;
	int i;
	for( i=0; i<2 ; i++ )
	{
		total = total << 4; //multiply 16?
		char digit;
		if( a[i] - '0' >= 0 && a[i] -'0' <= 9 )
			digit = a[i] - '0';
		else if ( a[i] - 'a' >= 0 && a[i] - 'a' <= 5 )
			digit = a[i] -'a' + 10;
		else
		{
			printf("hex conversion fail: %s\n", a);
			exit(-1);
		}
		total += digit;
	}

	return total;
}


#define CHAN_COUNT 8
int const BEATS_PER_MEASURE = 4;
int const SAMPLE_RATE = 44100;
float const TEMPO = 140;
#include "common.h"

static note createNote( time tStart, time tStop, char key, char instr ) 
{ 
        note n; 
	 
        n.start = tStart; 
        n.stop  = tStop; 
        n.note = key; 
        n.instrument = instr; 
        return n; 
} 
 


int main(int argc, char *argv[]) {
	
	if( argc <= 1 )
	{
		printf("Usage\n===============\n\t./trans [FILE INPUT] [optional FILE OUTPUT] \n\tOutputs binary file as lala.bin if no name is provided\n");
		exit(0);
	}

	int i;
	for( i=0 ; i<argc ; i++ )
		printf("%s\n", argv[i] );

	FILE * fptr;
	fptr = fopen( argv[1] , "r");
	
	if( fptr == NULL )
	{
		printf("read file error");
		exit(1);
	}

	//first pass gets notes per channel
	printf("[INFO] first pass\n");
	char line[24]; 
	int noteCount=0, channelsRead=0, currentChannel=-1;
	int notesPerChannel[ CHAN_COUNT ] = {0}; //TODO: dynamic array??

	//expects channel number
	if( NULL == fgets(line, 24, fptr) )
		printf("fail read\n");
	
	currentChannel = -1 * atoi(line);
	printf("Grabbing data for channel: %d\n", currentChannel);

	while( NULL != fgets(line, 24, fptr))
	{
		//printf("|%s", line);
		if( line[0] == '-')
		{
			notesPerChannel[ currentChannel ] = noteCount;
			printf("channel: %i notes; %i \n", currentChannel, noteCount);
			noteCount = 0;
			channelsRead++;
			currentChannel = -1 * atoi( line );
			printf("Found new channel: %d\n", currentChannel);
		}
		else
			noteCount++;
	}

	printf("found %d channels\n", channelsRead);

	//second pass loads data as notes
	printf("[INFO] second pass\n");
	int totalNotes = 0, j;
	for( j=0; j< CHAN_COUNT ; j++ )
		totalNotes += notesPerChannel[j];
	printf("total note count: %i \n", totalNotes);

	note * noteTable;
	if( NULL == (noteTable = malloc( sizeof(note) * totalNotes)) )
		printf("memory fail");
	
	rewind(fptr);
	fgets(line, 24, fptr);
	int f;
	int noteTableCount = 0;
	for( f=0; f<CHAN_COUNT; f++)
	{
		int k;
		for(k=0; k<notesPerChannel[f] ; k++)
		{
			fgets(line, 24, fptr);
			printf("LINES: %s\n", line); 
			int y;
			int gIndex=0;
			char gert[7];
			for(y=0; y< 2*7+7 ; y += 3)
			{	
				char word[2];
				word[0] = line[y];
				word[1] = line[y+1];
				gert[gIndex] = hexConverter( word );
				gIndex++;
			
			}
			//printf("%x %x %x\n", gert[0], gert[1], gert[2]); 
			time t1 = (time){ gert[0], gert[1], gert[2] };
			time t2 = (time){ gert[3], gert[4], gert[5] };
			noteTable[noteTableCount] =  createNote( t1, t2, gert[6], f );
			time * sss = & noteTable[noteTableCount].start;
			time * stop = & noteTable[noteTableCount].stop;
			printf("ch %i note %i note that channel %i %i %i %i %li %li\n", f, k, notesPerChannel[f], sss->measure, sss->beat, sss->subdivision, timeToClock( sss) , timeToClock(stop));
			noteTableCount++;
		}
		
		if( notesPerChannel[f] != 0 )
			fgets(line, 24, fptr);	
	}

	/**
	 * Third pass: interleave noteTable to create sortedTable
	 *
	 * An array of currentIndex for each channel is stored in chIndex
	 *   CHANNEL ==> [ 0 , 1 , 2 , 3 ]
	 *   ChIndex ==> [ 0 , 5 , 6 , 7, 8 ]
	 *                  
	 *   Where chIndex[n] <= sum of all chIndex[0] .. chIndex[n-1]
	 **/

	//TODO: FIx bug
	//master table only includes notes up to the last note in channel 0
	
	printf("[info] thid pass\n");

	note ** sortedTable;
	if( NULL == (sortedTable = malloc( sizeof(note) * totalNotes )))
		printf("sorted table fail");

		
	int chIndex[ CHAN_COUNT + 1]; //chIndex[n] points to current index of channel n in noteTable
	int chMaxSubdivision[ CHAN_COUNT ]; //chMAXsubdivision[n] is chIndex[n+1] -- supposed to prevent overwriting
	chIndex[0] = 0; 
	chMaxSubdivision[ CHAN_COUNT - 1] = totalNotes;
	int a;
	for( a=1; a<CHAN_COUNT ; a++)
	{
		chIndex[a] = chIndex[a-1] + notesPerChannel[a-1];  	
		chMaxSubdivision[a-1] = chIndex[a];
//		printf("%i %i %i %i\n", a, chIndex[a], a-1, chMaxSubdivision[a-1]);
	}

	int b;
	for(b=0;b< CHAN_COUNT ;b++)
		printf("ch: %i chIndex: %2i maxSub: %2i\n", b, chIndex[b], chMaxSubdivision[b]);
		

	chIndex[ CHAN_COUNT ] = chIndex[ CHAN_COUNT -1] + notesPerChannel[ CHAN_COUNT -1];
	printf( "[ASSERT] last chIndex %i == totalNotes %i\n", chIndex[ CHAN_COUNT ], totalNotes);
	assert( chIndex[ CHAN_COUNT ] == totalNotes );
	int e;
	for( e=0; e<totalNotes; e++)
	{
		note * earliestNote = NULL;
		int earliestIndex = -1;
		int f;
		for( f=0 ; f < CHAN_COUNT ; f++)
		{
			note * temp = &noteTable[ chIndex[f] ];
			if( chIndex[f] < chMaxSubdivision[f] && (earliestNote == NULL || timeToClock ( & temp->start ) < timeToClock( & earliestNote->start )) )
			{
				earliestNote = temp;
				earliestIndex = f;
			}
			
			printf("%i ", chIndex[f]);		
		//	printf("read channel %i start %li earl %li\n", f, temp->start, earliestNote->start);
		}
		printf("earliest channel: %i & count %i\n", earliestIndex, chIndex[earliestIndex]); 			
		sortedTable[e] = earliestNote;
		chIndex[earliestIndex]++;
	}

	//fourth pass write to binary
	printf("[info] fourth pass\n");
	FILE * final;

	const char * const outputPath = "./lala.bin";

	final = fopen( outputPath, "wb");

	int h;
	for( h=0 ; h<totalNotes ; h++)
		fwrite( sortedTable[h], sizeof(note), 1, final);

	printf("[info] OUT >> %s\n", outputPath);

	fclose(final);
	fclose(fptr);
	exit(0);

}
