#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include "lrstats-gl.h"
#include "Globals.h"
#include "Life.h"
#include "DEM.h"

//unsigned char rgb2[10][3] = { {255, 0, 0}, {0, 0, 255}, {255, 255, 0}, {255, 127, 0}, {127, 0, 127}, {0, 127, 127}, {0, 255, 255}, {127, 0, 255}, {127, 127, 127}, {255, 0, 127} } ;;



extern char *filename_dem;
extern unsigned char **Alive;

int main(int argc, char **argv){
	uint32_t w=0, h=0;
	//uint32_t width = 3600, height = 1800;
	//uint64_t year = 0;
	uint32_t n1=0, n2=0, n3=0;
	uint32_t species_c = 1;
	size_t size_of_species_t = 1000;
	uint32_t ten_most[10];
	unsigned char rgb[3];
	unsigned char rgb2[10][3] = {
		{255, 0, 0}, //red
		{170, 170, 38}, //puke
		{255, 255, 0}, //yellow
		{255, 127, 0}, //orange
		{127, 0, 127}, //purple
		{0, 127, 127}, //turqois
		{0, 255, 255}, //light blue
		{127, 64, 0}, //brown
		{127, 127, 127}, //grey
		{255, 255, 255} //white
	};
	//64, 127, 127
	struct Species *ten_s = malloc(sizeof(struct Species)*10);

	struct Species *species_t = malloc(sizeof(struct Species) * size_of_species_t);
	uint32_t *species_totals = malloc(sizeof(uint32_t) * size_of_species_t);
	size_t total_read = 0;
	uint32_t total_population = 0;

	No_Exit = 1;

	FILE *fp = fopen("BACKUP.lr", "rb");
	if(!fp){
		printf("error opening file!\n");
		return 0;
	}

    //char *filename = (char *)malloc(strlen("myout.test") + 1);
    //strcpy(filename, "myout.test");
    filename_dem = (char *)malloc(strlen("myout.test") + 1);
    strcpy(filename_dem, "myout.test");


    if( (int)Load_Terrain() ){
        printf("Load Terrain Error!\n");
        exit(1);
    }
    printf("read DEM!\n");


	//Load_Terrain(char *filename);

	Allocate_Life_Array();

    Alive = (unsigned char **)malloc(sizeof(unsigned char *)*HEIGHT);
    for(h=0; h<HEIGHT; h++){
        Alive[h] = (unsigned char *)malloc(sizeof(unsigned char)*(size_t)ceil(WIDTH/8));
        (void)memset( (void *)Alive[h], '\0', sizeof(unsigned char)*(size_t)ceil(WIDTH/8) );
    }

	//stats = (struct Stats *)malloc( sizeof(struct Stats) * regions);
    //total_read += fread((void *)&stats_t, sizeof(struct Stats_T), 1, fp);
    //for(h=0; h<height; h++){
      //  for(w=0; w<width; w++){
        //    total_read += fread((void *)life[h][w], 1, sizeof(struct Species), fp);
        //}
    //}

    total_read += fread((void *)&stats_t, 1, sizeof(struct Stats_T), fp);
    for(h=0; h<HEIGHT; h++){
        total_read += fread((void *)Alive[h], 1, sizeof(unsigned char)*ceil(WIDTH/8), fp);
    }


    for(h=0; h<HEIGHT; h++){
        for(w=0; w<WIDTH; w++){
            total_read += fread((void *)life[h][w], 1, sizeof(struct Species), fp);
        }
    }



//    ia = malloc(sizeof(struct image_attr));
    //ia->image = malloc(sizeof(unsigned char)*height*width*3);
    //ia->width = width;
    //ia->height = height;
    //ia->cur_sealevel = start_sealevel;

    //total_read += fread((void *)&stats_t.cur_sealevel, 1, sizeof(int16_t),fp);
    //total_read += fread((void *)&stats_t.sea_rising, 1, sizeof(char), fp);
    //total_read += fread((void *)&stats_t.year, 1, sizeof(uint32_t), fp);
	printf("Total_read(bytes):%zu\n", total_read);
	species_totals[0] = 9;
	//(void)memset((void *)species_totals, '\0', sizeof(uint32_t)*species_c);

	for(h=0; h<HEIGHT; h++){
		for(w=0; w<WIDTH; w++){
			//if(life[h][w]->alive){
			if(IS_SET(Alive, h, w) ){
				(void)memcpy((void *)&species_t[0], (const void *)life[h][w], sizeof(struct Species) );
				species_totals[0] = 0;
				break;
			}//else{
			//	(void)memset((void *)&stats[n1], '\0', sizeof(struct Stats) );
			//}
		}
		if(species_totals[0] == 0)
			break;
	}
	for(h=0; h<HEIGHT; h++){
		for(w=0; w<WIDTH; w++){

			//if(life[h][w]->alive){
			if(IS_SET(Alive, h, w) ){
				total_population++;
				for(n1=0; n1<species_c; n1++){
					if( Is_Same_Species(&species_t[n1], life[h][w]) ){
						species_totals[n1]++;
						//continue;
						goto Next_Tribe;
					}
				}
				species_c++;
				if(species_c > size_of_species_t){
					size_of_species_t += 500;
					species_t = (struct Species *)realloc(species_t, sizeof(struct Species) * size_of_species_t);
					species_totals = (uint32_t *)realloc(species_totals, sizeof(uint32_t) * size_of_species_t);
					//set all new species_totals = 0;
					for(n3=species_c; n3<size_of_species_t; n3++){
						(void)memset((void *)&species_t[n3], '\0', sizeof(struct Species) );
						//(void)memset((void *)&species_totals[n3], '\0', sizeof(struct Species) );
						species_totals[n3] = 0;
					}
				}
				species_totals[species_c-1] = 1;
				(void)memcpy((void *)&species_t[species_c-1], (const void *)life[h][w], sizeof(struct Species) );
			}
			Next_Tribe:
			;
		}
	}
	for(n1=0; n1<10; n1++)
		ten_most[n1] = 0;

	printf("%u total population\n", total_population);
	printf("%u unique species alive\n", species_c);
	uint32_t last_highest = 0;
	last_highest--;
	uint32_t highest = 0;

	for(n2=0; n2<10; n2++){
		for(n1=0; n1<species_c; n1++){
			if(species_totals[n1] < last_highest){
				if(species_totals[n1] > highest){
				//if(species_totals[n1] < last_highest){
					highest = species_totals[n1];
					ten_most[n2] = highest;
					(void)memcpy((void *)&ten_s[n2], (const void *)&species_t[n1], sizeof(struct Species) );
				}
			}
		}
		last_highest = highest;
		highest = 0;
	}

	/*
	for(n1=0; n1<species_c; n1++){
		for(n2=0; n2<10; n2++){

			if(species_totals[n1] > ten_most[n2]){
				ten_most[n2] = species_totals[n1];
				//species_totals[n1] = 0;
				(void)memcpy((void *)&ten_s[n2], (const void *)&species_t[n1], sizeof(struct Species) );
				break;
			}

		}
	}
	*/

	//sums up to 1658880000 maximum value
	float social_factor = 0;
	float migration_factor = 0;
	float fight_flight_balance = 0;
	float interspecies_violence = 0;
	float imunity = 0;
	float avg_age = 0;
	//unsigned char c_count[] = {0, 0, 0};

	n2 = species_c < 10 ? species_c : 10;

	printf("%u most populous:\n", n2);
	printf("black color for all others\n");

	printf("\t\t\tSpecies_Traits(0 to +3)\t\t:\t\tSub_Species_Traits(avgs)\n\n");
	printf("%%Pop_t  Pop rgb(stats)/(sim)  intel  stren  speed  temp_l  temp_h  max_age : ");
	printf("social_factor  migration_f  fight/flight  interspecies_violence  imunity  avg_age\n");

	for(n1=0; n1<n2; n1++){
		Gen_Tribe_Color(&ten_s[n1], rgb);
		//printf("%u\t %u\t %u,%u,%u\t: %u\t %u\t %u\t %u\t %u\t %u\n", 
		printf("%.03lf%%\t%u\t%u,%u,%u/%u,%u,%u\t", ( (double)ten_most[n1]/(double)total_population )*100, ten_most[n1], rgb2[n1][0], rgb2[n1][1], rgb2[n1][2], rgb[0], rgb[1], rgb[2]);
		//printf("#%u population: %u map rgb: %u,%u,%u\n", n1, ten_most[n1], rgb[0], rgb[1], rgb[2]);
		//printf("\tspecies traits (0 to +3 range):\n");
		ten_s[n1].intelligence = floor(ten_s[n1].intelligence/4)*4;
		ten_s[n1].strength = floor(ten_s[n1].strength/4)*4;
		ten_s[n1].speed = floor(ten_s[n1].speed/4)*4;
		ten_s[n1].temp_l = floor(ten_s[n1].temp_l/4)*4;
		ten_s[n1].temp_h = floor(ten_s[n1].temp_h/4)*4;
		ten_s[n1].max_age = floor(ten_s[n1].max_age/4)*4;

		printf("%u\t%u\t%u\t%u\t%u\t%u\t:\t",ten_s[n1].intelligence, ten_s[n1].strength,
		//printf("\t\tintelligence: %u strength: %u speed: %u temp_l: %u temp_h: %u max_age: %u\n", ten_s[n1].intelligence, ten_s[n1].strength,
				ten_s[n1].speed, ten_s[n1].temp_l, ten_s[n1].temp_h, ten_s[n1].max_age);
		for(h=0; h<HEIGHT; h++){
			for(w=0; w<WIDTH; w++){
				//if(life[h][w]->alive){
				if(IS_SET(Alive, h, w) ){
					if( Is_Same_Species(&ten_s[n1], life[h][w]) ){
						social_factor += life[h][w]->social_factor;
						migration_factor += life[h][w]->migration_factor;
						fight_flight_balance += life[h][w]->fight_flight_balance;
						interspecies_violence += life[h][w]->interspecies_violence;
						imunity += life[h][w]->imunity;
						avg_age += life[h][w]->cur_age;
					}
				}
			}
		}
		social_factor /= ten_most[n1];
		migration_factor /= ten_most[n1];
		fight_flight_balance /= ten_most[n1];
		interspecies_violence /= ten_most[n1];
		imunity /= ten_most[n1];
		avg_age /= ten_most[n1];

		//printf("\tsub-species traits (averaged):\n");
		 //printf("\t\tsocial_factor: %u migration_factor: %u fight/flight: %u interspecies_violence: %u imunity: %u\n", ten_s[n1].social_factor, 
		 //		ten_s[n1].migration_factor, ten_s[n1].fight_flight_balance, ten_s[n1].interspecies_violence, ten_s[n1].imunity);
		//printf("\t\tsocial_factor: %.02f migration_factor: %.02f fight/flight: %.02f interspecies_violence: %.02f imunity: %.02f avg_age: %.02f\n",
		printf("%.02f\t%.02f\t%.02f\t%.02f\t%.02f\t%.02f\n",
			social_factor, migration_factor, fight_flight_balance, interspecies_violence, imunity, avg_age);

		social_factor = 0;
		migration_factor = 0;
		fight_flight_balance = 0;
		interspecies_violence = 0;
		imunity = 0;
		avg_age = 0;

			//printf("\t\tintelligence: %u strength: %u speed: %u social_factor: %u\n", ten_s[n1].intelligence, ten_s[n1].strength,
			//		ten_s[n1].speed, ten_s[n1].social_factor);
			//printf("\t\tffb: %u iv: %u ma: %u mf: %u th: %u tl: %u\n", ten_s[n1].fight_flight_balance, ten_s[n1].interspecies_violence,
			//		ten_s[n1].max_age, ten_s[n1].migration_factor, ten_s[n1].temp_h, ten_s[n1].temp_l);
	}


	//remove all species from map that aren't in the top 10, and add better coloring


    for(h=0; h<HEIGHT; h++){
        for(w=0; w<WIDTH; w++){
            if(ia->dem[h][w] > stats_t.cur_sealevel){
                //if(!life[h][w]->alive){
				if( !IS_SET(Alive, h, w) ){
                    rgb[0] = 0;
                    rgb[1] = 255;
                    rgb[2] = 0;
                    //continue;
                }else{

					for(n1=0; n1<n2; n1++){
						if( Is_Same_Species(&ten_s[n1], life[h][w]) ){
							rgb[0] = rgb2[n1][0];
							rgb[1] = rgb2[n1][1];
							rgb[2] = rgb2[n1][2];
							break;
						}
						//if(n1 == n2-1){
						rgb[0] = 0;
						rgb[1] = 0;
						rgb[2] = 0;
						//}
					}
                    //Gen_Tribe_Color(life[n1][n2], rgb);
                }
            }else{
				rgb[0] = 0;
				rgb[1] = 0;
				rgb[2] = 255;
			}
            ia->image[h*WIDTH*3+(w*3)]   = rgb[0];
            ia->image[h*WIDTH*3+(w*3+1)] = rgb[1];
            ia->image[h*WIDTH*3+(w*3+2)] = rgb[2];
        }
    }


	glutInit(&argc,argv);
	Run_GL(NULL);


    for(h=0; h<HEIGHT; h++){
        free(Alive[h]);
        //free(Fought[n1]);
        //free(Mated[n1]);
        for(w=0; w<WIDTH; w++){
            free(life[h][w]);
        }
        free(life[h]);
    }
    free(Alive);
	free(life);
	free(ten_s);
	free(species_t);
	free(species_totals);
	//free(species_t);
	fclose(fp);

	return 0;
}