#include "DEM.h"

void Adjust_Sea_Level(int load){
	static int sea_level_chng = 100;
	static int is_rising = 0;
	// 1m per 1K years
	if(load){
		sea_level_chng = stats_t.cur_sealevel;
		is_rising = stats_t.sea_rising;
		return;
	}
	if(is_rising){
		if(sea_level_chng == 100){
			is_rising = 0;
		}else{
			sea_level_chng++;
		}
	}else{
		if(sea_level_chng == -128){
			is_rising = 1;
		}else{
			sea_level_chng--;
		}
	}
	stats_t.cur_sealevel = sea_level_chng;
	stats_t.sea_rising = is_rising;
}

void Adjust_Climate(int load){
    static float temp_chng = 32; //starting at high temp
    static int is_rising = 0;
	//every 10K years you'll get a 2c temp change

    if(load){
        temp_chng = stats_t.cur_temp;
        is_rising = stats_t.temp_rising;
        return;
    }
	if(is_rising){
        if(temp_chng > 32){
             is_rising = 0;
         }else{
            temp_chng+=0.2;
         }
	}else{
       if(temp_chng < 28){
           is_rising = 1;
       }else{
           temp_chng-=0.2;
       }
	}
    stats_t.cur_temp = temp_chng;
    stats_t.temp_rising = is_rising;
}

int Load_Terrain(void){
	FILE *fp = fopen(filename_dem, "rb");
	if(!fp){
		printf("Error opening file: %s\n", filename_dem);
		return 1;
	}
	const int start_sealevel = 100;

	ia = malloc(sizeof(struct image_attr));
	ia->image = malloc(sizeof(unsigned char)*HEIGHT*WIDTH*3);
	stats_t.cur_sealevel = start_sealevel;
	stats_t.sea_rising = 0;
	stats_t.cur_temp = 32;
	stats_t.temp_rising = 0;

	char two_b[2];
	union{ char a[2]; int16_t b;}x;
	unsigned int count1, count2;
	unsigned char rgb[3];
	size_t total_read = 0;

	ia->dem = (int16_t **)malloc(sizeof(int16_t *)*HEIGHT);
	for(count1=0; count1<HEIGHT; count1++){
		ia->dem[count1] = (int16_t *)malloc(sizeof(int16_t)*WIDTH);
	}
	for(count1=0; count1<HEIGHT; count1++){
		for(count2=0; count2<WIDTH; count2++){
			total_read += fread(&two_b, 1, 2, fp);
			x.a[0] = two_b[0];
			x.a[1] = two_b[1];
			ia->dem[count1][count2] = x.b;
			if(x.b < start_sealevel){
				rgb[0] = 0;
				rgb[1] = 0;
				rgb[2] = 255;
			}else{
				rgb[0] = 0;
				rgb[1] = 255;
				rgb[2] = 0;
			}
			ia->image[count1*WIDTH*3+(count2*3)] = rgb[0];
			ia->image[count1*WIDTH*3+(count2*3+1)] = rgb[1];
			ia->image[count1*WIDTH*3+(count2*3+2)] = rgb[2];
		}
	}
	fclose(fp);
	if(total_read != 2*HEIGHT*WIDTH){
		printf("Error: fread sum does for '%s' not match with compile-time DEM dimensions!\n", filename_dem);
		printf("\tread %zu expected %u\n", total_read, 2*HEIGHT*WIDTH);
		for(count1=0; count1<HEIGHT; count1++){
			free(ia->dem[count1]);
		}
		free(ia->dem);
		free(ia->image);
		free(ia);
		return 1;
	}
	printf("Loaded DEM from '%s'\n", filename_dem);
	printf("\tread %zu bytes\n", total_read);

	return 0;
}

void Gen_Detailed_Counts(void){
	//printf 10 most numerous species info
	//and update stats_t
	uint32_t h; //, w;
	//uint32_t total_living = 0;
	uint32_t chng = 0;

	//for(h=0; h<HEIGHT; h++){
	//	for(w=0; w<WIDTH; w++){
	//		if(life[h][w]->alive){
	//			total_living++;
	//		}
	//	}
	//}
	for(h=0; h<Threads; h++){
            stats_t.disease += stats[h].disease;
            stats_t.drown += stats[h].drown;
			stats_t.exposure += stats[h].exposure;
            stats_t.old_age += stats[h].old_age;
            stats_t.died_attacking += stats[h].died_attacking;
            stats_t.died_defending += stats[h].died_defending;
            stats_t.new_life += stats[h].new_life;
            stats_t.new_species += stats[h].new_species;
			//stats_t.total_runtime += runtime
			//stats_t.total_living += stats[h].total_living;
	}
	stats_t.total_runtime += Backup_Freq_Runtime;
	//printf("Total Living: %u\n\n", total_living);
	printf("Year: %u\n", stats_t.year); 
	if(stats_t.sea_rising){
		printf("Current: Sec/Year %.04lfs cur_sealevel %dm rising +1m/1Kyears", Backup_Freq_Runtime/1000, stats_t.cur_sealevel);
	}else{
		printf("Current: Sec/Year %.04lfs cur_sealevel %dm falling -1m/1Kyears", Backup_Freq_Runtime/1000, stats_t.cur_sealevel);
	}
	printf(" equatorial mean temp: %.02fc changing: %.02fc/1Kyears\n", stats_t.cur_temp, (stats_t.temp_rising ? 0.2 : -0.2) );
	printf("Total: Runtime %.02lf hrs Avg Sec/Year %lfs\n\n", (double)stats_t.total_runtime/60/60, (double)stats_t.total_runtime/stats_t.year);

	printf("\tdisease: %lu\n", stats_t.disease);
	for(h=0; h<Threads; h++){
		chng += stats[h].disease;
	}
	printf("\t\tchng: %u\n",chng); 

	printf("\tdrown: %lu\n", stats_t.drown);
	chng=stats[0].drown;
	for(h=1; h<Threads; h++){
		chng += stats[h].drown;
	}
	printf("\t\tchng: %u\n",chng);

    printf("\texposure: %lu\n", stats_t.exposure);
    chng=stats[0].exposure;
    for(h=1; h<Threads; h++){
        chng += stats[h].exposure;
    }
    printf("\t\tchng: %u\n",chng);

	printf("\told_age: %lu\n", stats_t.old_age);
	chng=stats[0].old_age;
	for(h=1; h<Threads; h++){
		chng += stats[h].old_age;
	}
	printf("\t\tchng: %u\n",chng);

	printf("\tdied_attacking: %lu\n", stats_t.died_attacking);
	chng=stats[0].died_attacking;
	for(h=1; h<Threads; h++){
		chng += stats[h].died_attacking;
	}
	printf("\t\tchng: %u\n",chng);

	printf("\tdied_defending: %lu\n", stats_t.died_defending);
	chng=stats[0].died_defending;
	for(h=1; h<Threads; h++){
		chng += stats[h].died_defending;
	}
	printf("\t\tchng: %u\n",chng);

	printf("\tnew_life: %lu\n", stats_t.new_life);
	chng=stats[0].new_life;
	for(h=1; h<Threads; h++){
		chng += stats[h].new_life;
	}
	printf("\t\tchng: %u\n",chng);

	printf("\tnew_species: %lu\n", stats_t.new_species);
	chng=stats[0].new_species;
	for(h=1; h<Threads; h++){
		chng += stats[h].new_species;
	}
	printf("\t\tchng: %u\n\n",chng);
	//for(h=0; h<HEIGHT; H++
	//printf("\tTotal_Population: %lu\n", stats_t.total_living);
	//chng=stats[0].total_living;
	//for(h=1; h<Threads; h++){
	//	chng += stats[h].total_living;
	//}
	//printf("\t\tchng: %u\n\n",chng);

	//printf("Total Living: %u\n\n", total_living);
	Backup_Freq_Runtime = 0;
	Year_Runtime = 0;
	//stats_t.total_living = 0;
	//reset thread stats
	for(h=0; h<Threads; h++){
		(void)memset((void *)&stats[h], '\0', sizeof(struct Stats) );
	}
}

int Save_Current_State(void){
	FILE *fp = fopen(filename_backup_save, "wb");
    if(!fp){
        printf("Error opening file: %s\n", filename_backup_save);
        return 1;
    }
	uint32_t w = 0, h = 0;
	size_t bytes = 0;
	uint64_t total_living = 0;
	for(h=0; h<HEIGHT; h++){
		if(!life_speed_up_Y[h])
			continue;
		for(w=0; w<WIDTH; w++){
			if(!life_speed_up_X[w])
				continue;
			if(life[h][w]->alive)
				total_living++;
		}
	}
	stats_t.total_living = total_living;

	bytes += fwrite((const void *)&stats_t, sizeof(struct Stats_T), 1, fp);
	for(h=0; h<HEIGHT; h++){
		for(w=0; w<WIDTH; w++){
			bytes += fwrite((const void *)life[h][w], sizeof(struct Species), 1, fp);
		}
	}
/*
	bytes += fwrite((const void *)&stats_t.year, sizeof(uint32_t), 1, fp);
	bytes += fwrite((const void *)&stats_t.cur_temp, sizeof(float), 1, fp);
	bytes += fwrite((const void *)&stats_t.cur_sealevel, sizeof(int16_t), 1, fp);
	bytes += fwrite((const void *)&stats_t.sea_rising, sizeof(char), 1, fp);
	bytes += fwrite((const void *)&stats_t.temp_rising, sizeof(char), 1, fp);
*/
	printf("Saved current state to '%s'!\n", filename_backup_save);
	printf("\tbytes wrote: %zu\n", bytes);
	printf("\tTotal_Population: %lu\n\n", total_living);
	//free(filename);
	fclose(fp);
	//if(bytes != (sizeof(uint32_t) + sizeof(float) + sizeof(int16_t) + 2 + sizeof(struct Species)) )
	//	return 1;
	//add crc later

	return 0;
}

int Load_State(void){
    FILE *fp = fopen(filename_backup_load, "rb");
    if(!fp){
        printf("Error opening file: %s\n", filename_backup_load);
        return 1;
    }
	uint32_t w = 0, h = 0;
	size_t bytes = 0;

	bytes += fread((void *)&stats_t, sizeof(struct Stats_T), 1, fp);
	for(h=0; h<HEIGHT; h++){
		for(w=0; w<WIDTH; w++){
			bytes += fread((void *)life[h][w], sizeof(struct Species), 1, fp);
		}
	}
/*
	bytes += fread((void *)&stats_t.year, sizeof(uint32_t), 1, fp);
	bytes += fread((void *)&stats_t.cur_temp, sizeof(float), 1, fp);
	bytes += fread((void *)&stats_t.cur_sealevel, sizeof(int16_t), 1, fp);
	bytes += fread((void *)&stats_t.sea_rising, sizeof(char), 1, fp);
	bytes += fread((void *)&stats_t.temp_rising, sizeof(char), 1, fp);
*/
	//bytes += fread((void *)life_speed_up_H, sizeof(char)*height, 1, fp);
	//bytes += fread((void *)life_speed_up_W, sizeof(char)*width, 1, fp);
	//stats_t.cur_sealevel = -100;
	//stats_t.sea_rising = 0;

	printf("Loaded state from '%s'\n", filename_backup_load);
	printf("\tbytes read: %zu\n", bytes);
	//free(filename);
	fclose(fp);
	return 0;
}