#include "hsc.h"
#include "string.h"
#include<limits.h>
#include <curl/curl.h>

HSC::HSC()
{
	init();
}
HSC::~HSC()
{
	destroy();
}

void HSC::destroy()
{
	if(bImage != NULL) destroy_bitmap(bImage);
}

void HSC::get_local()
{
	int iIndex, j;
	PACKFILE *f = pack_fopen("./data/hsc", "r");

	clear_local();
	if(f)
	{
		char cName[CHAR_SIZE];
		int iScore;
		int iLevel;
		float iVersion;
		int iLow_Score = INT_MAX;

		GAME.low_score = INT_MAX;

		while(!pack_feof(f))
		{
			pack_fread(&cName, sizeof(char) * CHAR_SIZE, f);
			pack_fread(&iScore, sizeof(int), f);
			pack_fread(&iVersion, sizeof(float), f);
			pack_fread(&iLevel, sizeof(int), f);

			//find the lowest score
			iIndex = -1;
			iLow_Score = INT_MAX;
			for(j = 0; j < MAX_STATS; j++)
			{
				if(lStats[j].points < iLow_Score)
				{
					iIndex = j;
					iLow_Score = lStats[j].points;
				}
			}
			
			//push high score
			if(iIndex != -1 && iScore > lStats[iIndex].points - 10)
			{
				if(iScore < GAME.low_score)
					GAME.low_score = iScore;
				lStats[iIndex].points = iScore;
				lStats[iIndex].version = 0;//int(iVersion);
				lStats[iIndex].level = iLevel;
				strcpy(lStats[iIndex].cName, cName);				
			}
		}		

		pack_fclose(f);
	}

	sort();
}

int HSC::get_low()
{
	int iLow_Score = INT_MAX;
	int i;

	get_local();
	get_online();

	for(i = 0; i < MAX_STATS; i++)
		if(lStats[i].points < iLow_Score)
			iLow_Score = lStats[i].points;

	for(i = 0; i < MAX_ONLINE_STATS; i++)
		if(oStats[i].points < iLow_Score)
			iLow_Score = oStats[i].points;

	return iLow_Score;

}


void HSC::sort()
{
	int iIndex = 0;
	int iScore;

	//Find the highest score
	for(int j = 0; j < MAX_STATS; j++)
	{
		iScore = lStats[j].points;
		iIndex = j;
		for(int i = j; i < MAX_STATS; i++)
		{
			if(lStats[i].points > iScore)
			{
				iIndex = i;
				iScore = lStats[i].points;
			}
		}		
		if(iIndex != j) hsc_flip(lStats[j], lStats[iIndex]);
	}	

}


void HSC::hsc_flip(STATS &s1, STATS &s2)
{
	STATS sTemp;

	sTemp.level = s1.level;
	sTemp.points = s1.points;
	sTemp.version = s1.version;
	strcpy(sTemp.cName, s1.cName);

	s1.level = s2.level;
	s1.points = s2.points;
	s1.version = s2.version;
	strcpy(s1.cName, s2.cName);

	s2.level = sTemp.level;
	s2.points = sTemp.points;
	s2.version = sTemp.version;
	strcpy(s2.cName, sTemp.cName);
}

void HSC::draw(BITMAP *bDisplay, int y, int S)
{
	set_palette((RGB *) GAME.score_palette);
	rectfill(bImage, 0, 0, bImage->w, bImage->h, MASK);
	textprintf_ex(bImage, GAME.score_font, 10, 10, -1,-1, "Pos");
	textprintf_ex(bImage, GAME.score_font, 80, 10, -1,-1, "Name");					
	textprintf_ex(bImage, GAME.score_font, 400, 10, -1,-1, "Score");					

	if(y < -1100) y = -1100;

	for(int i = 0; i < MAX_STATS; i++)
	{
		if(lStats[i].points != 0)
		{
			textprintf_ex(bImage, GAME.score_font, 10, (i + 2) * 32, -1, -1, "%d.", i + 1);
			textprintf_ex(bImage, GAME.score_font, 80, (i + 2) * 32, -1, -1, "%s", lStats[i].cName);					
			textprintf_right_ex(bImage, GAME.score_font, 490, (i + 2) * 32, -1, -1, "%d", lStats[i].points);					
		}
	}
	
	stretch_sprite(bDisplay, bImage, 0, y, bDisplay->w - S, bImage->h - S);

}

void HSC::draw_online(BITMAP *bDisplay, int y, int S)
{
	set_palette((RGB *) GAME.score_palette);
	rectfill(bImage, 0, 0, bImage->w, bImage->h, MASK);
	textprintf_ex(bImage, GAME.score_font, 10, 10, -1, -1,"Pos");					
	textprintf_ex(bImage, GAME.score_font, 80, 10, -1, -1, "Name");					
	textprintf_ex(bImage, GAME.score_font, 400, 10, -1, -1, "Score");					
	
	for(int i = 0; i < MAX_ONLINE_STATS; i++)
	{
		if(oStats[i].points != 0 && strcmp(oStats[i].cName, "Toggles_Version") != 0)
		{
			
			textprintf_ex(bImage, GAME.score_font, 10, (i + 2) * 32, -1, -1, "%d.", i + 1);
			textprintf_ex(bImage, GAME.score_font, 80, (i + 2) * 32, -1, -1, "%s", oStats[i].cName);					
			textprintf_right_ex(bImage, GAME.score_font, 490, (i + 2) * 32, -1, -1, "%d", oStats[i].points);							
		}
	}
	
	stretch_sprite(bDisplay, bImage, 0, y, bDisplay->w - S, bImage->h - S);	

}

bool HSC::local_update()
{
	int i = 0;
	bool quit = false;
	char cTemp[CHAR_SIZE];
	float iVersion = 1.9;

	strcpy(cTemp, "Computer");

	PACKFILE *f = pack_fopen("./data/hsc", "w");
	if(f)
	{
	
		for(i = 0; i < MAX_STATS; i++)
		{
			pack_fwrite(&lStats[i].cName, sizeof(char) * CHAR_SIZE, f);
			pack_fwrite(&lStats[i].points, sizeof(int), f);
			pack_fwrite(&lStats[i].version, sizeof(float), f);
			pack_fwrite(&lStats[i].level, sizeof(int), f);
				
			if(quit != true && GAME.gScore->points > lStats[i].points)
			{
				quit = true;
			
				pack_fwrite(&GAME.cName, sizeof(char) * CHAR_SIZE, f);
				pack_fwrite(&GAME.gScore->points, sizeof(int), f);
				pack_fwrite(&iVersion, sizeof(float), f);
				pack_fwrite(&GAME.level, sizeof(int), f);
				
			}
		}
		pack_fclose(f);
	}


	return quit;
}

bool HSC::online_check()
{
	bool quit = false;
	int i  = 0;

	while(i < MAX_ONLINE_STATS && quit != true)
	{
		// If the current score is greater than any listed
		// online stats, then we need to write to the file.
		if(GAME.gScore->points > oStats[i].points)
			quit = true;
		
		i++;
	}

	return quit;
}


long HSC::calculateCode(const char *name, int score)
{
	long sum = 0;
	for(unsigned int i = 0; i < strlen(name); i++)
		sum += name[i] * (1 << i);
	
	sum ^= (score + score << 8);
	sum &= 0x7fffffff;

	return sum;
}

void HSC::online_submit()
{
	//int i = 0;
	//bool quit = false;	
	//float iVersion = fVERSION;

	/*if(get_online_version() == 1)
	{
		allegro_message("ERROR:  Version incompatibility.  Please go to http://www.silvey-games.blogspot.com to get the most recent version.");
		return;
	}*/

	char http[150];
	char action[20];
	char name[CHAR_SIZE];
	int score, level;
	char version[10];
	char url_buf[256];
	CURL *curl;
		
	curl = curl_easy_init();
	if(curl)
	{
		strcpy(http, "http://comp.uark.edu/~spsilve/toggles/highscore.php");
		strcpy(action, "submit");
		strcpy(name, GAME.cName);
                if(strlen(name) >= CHAR_SIZE) name[CHAR_SIZE - 1] = 0;
                for(unsigned int i = 0; i < strlen(name) ; i++)
                  if(name[i] == ' ') name[i] = '_';
                if(strcmp(name, "") == 0) strcpy(name, "bad_data");
		score = GAME.gScore->points;
                if(score < 0) score = 0;
		strcpy(version, VERSION);
		level = GAME.level;
		sprintf(url_buf, "%s?action=%s&name=%s&score=%d&version=%s&level=%d&code=%d", http, action, name, score, version, level, calculateCode(name,score));
		curl_easy_setopt(curl, CURLOPT_URL, url_buf);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
		curl_easy_perform(curl);
		curl_easy_cleanup(curl);	
	}
	
	return;
}

static char *dl_buf;
size_t get_hsc(void *ptr, size_t size, size_t nmemb, void *stream)
{
	dl_buf = (char *) malloc((strlen((char *) ptr) + 1) * sizeof(char));
	strcpy(dl_buf, (char *) ptr);
	return size * nmemb;
	//return strlen((char *) ptr) + 1;
}

void HSC::get_online()
{
	char url_buf[256];
	char http[150];
	char action[20];	
	//long value = 30;
	CURL *curl;
	CURLcode res;

	//text_mode(0);	
	textprintf_ex(screen, font, 1, 1, WHITE, -1, "Loading High Scores...");
	//text_mode(MASK);	

	curl = curl_easy_init();
	if(curl)
	{
		strcpy(http, "http://comp.uark.edu/~spsilve/toggles/highscore.php");
		strcpy(action, "get");
		sprintf(url_buf, "%s?action=%s", http, action);
		curl_easy_setopt(curl, CURLOPT_URL, url_buf);	
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, get_hsc);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
		res = curl_easy_perform(curl);		
		curl_easy_cleanup(curl);
		if(res == CURLE_OK) set_online();
		else 
			allegro_message("ERROR:  curl_easy_perform could not write data.  errcode = %d", res);
		//set_online();
		
		if(dl_buf != NULL)
		{
			free(dl_buf);
			dl_buf = NULL;
		}
	}
}

int HSC::get_online_version()
{
	char url_buf[256];
	char http[150];
	char action[20];	
	//long value = 30;
	char *ctemp=NULL;
	CURL *curl;
	CURLcode res;

	//text_mode(0);	
	textprintf_ex(screen, font, 1, 1, WHITE, -1, "Loading Version...");
	//text_mode(MASK);	
		
	curl = curl_easy_init();
	if(curl)
	{
		strcpy(http, "http://comp.uark.edu/~spsilve/toggles/version.php");
		strcpy(action, "version");
		sprintf(url_buf, "%s?action=%s", http, action);
		curl_easy_setopt(curl, CURLOPT_URL, url_buf);	
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, get_hsc);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
		res = curl_easy_perform(curl);		
		
		if(res == CURLE_OK) 
		{
			ctemp = new char[(strlen(dl_buf) + 1) * sizeof(char)];
			strcpy(ctemp, dl_buf);			
			ctemp[6] = '\0';
						
		}
		else 
			allegro_message("ERROR:  curl_easy_perform could not get the current version.  errcode = %d", res);
		
		curl_easy_cleanup(curl);
		if(dl_buf != NULL)
		{
			free(dl_buf);
			dl_buf = NULL;
		}
	}

	if(strcmp(ctemp, VERSION) == 0)
		return 0;
	else
		return 1;
}


void HSC::set_online()
{
	int iIndex = 0, iparameter = 0;
	char *ctemp, *cnext;
	char ccurrent[256];
	unsigned int i = 0;

	ctemp = new char[(strlen(dl_buf) + 1) * sizeof(char)];
	strcpy(ctemp, dl_buf);
	cnext = ctemp;
	
	while(ctemp[i] != '\0' && i < strlen(dl_buf))
	{
		if(ctemp[i] == '/')
		{
			cnext = ctemp + i + 1;
			ctemp[i] = '\0';
			strcpy(ccurrent, ctemp);
			
			switch(iparameter)
			{
				case 0:	
					strcpy(oStats[iIndex].cName, ccurrent); 
					break;
				case 1: 
					strcpy(oStats[iIndex].cversion, ccurrent); 
					break;
				case 2: oStats[iIndex].level = atoi(ccurrent); break;
				case 3: oStats[iIndex++].points = atoi(ccurrent); break;
			}			
			iparameter++;
			if(iparameter > 3) iparameter = 0;
			ctemp = cnext;
			i = 0;
		}
		i++;
	}		
}


void HSC::init()
{
	clear();
	bImage = create_bitmap_check(500, 3300);
	dl_buf = NULL;
	
}

void HSC::clear()
{
	clear_local();
	clear_online();
}

void HSC::clear_local()
{

	for(int i = 0; i < MAX_STATS; i++)
	{
		lStats[i].level = 0;
		lStats[i].points = 0;
		lStats[i].version = 0;
		strcpy(lStats[i].cName, "");		
	}
}

void HSC::clear_online()
{
	for(int i = 0; i < MAX_ONLINE_STATS; i++)
	{
		oStats[i].level = 0;
		oStats[i].points = 0;
		strcpy(oStats[i].cversion, "");
		strcpy(oStats[i].cName, "");
	}
}


