#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <malloc.h>
#include <sys/time.h>
#include "Random.h"

int main(int argc, char **argv){
	uint32_t roll_n = 0;
	uint32_t max_rolls = 100000;
	uint32_t max_dice_to_roll = 6;
	uint32_t cur_dice_rolled = 1;
	uint32_t num1 = 0;
	uint32_t num2 = 0;
	char roll_results[6] = {0, 0, 0, 0, 0, 0};
	uint32_t *roll_stats = (uint32_t *)malloc(sizeof(uint32_t)*max_dice_to_roll);
	(void)memset(roll_stats, '\0', sizeof(uint32_t)*max_dice_to_roll);
	struct timeval cur;
	gettimeofday(&cur, NULL);
	uint64_t s = (uint64_t)cur.tv_usec + 3;
	/*
	uint32_t **roll_stats = (uint32_t **)malloc(sizeof(uint32_t *)*max_dice_to_roll);
	for(num1=0; num1<max_dice_to_roll; num1++){
		roll_stats[num1] = (uint32_t *)malloc(sizeof(uint32_t)*2);
		(void)memset(&roll_stats[num1], '\0', sizeof(uint32_t)*2);
	}
	*/
	for(cur_dice_rolled=1; cur_dice_rolled<=max_dice_to_roll; cur_dice_rolled++){
		for(roll_n=0; roll_n<max_rolls; roll_n++){
			for(num1=0; num1<cur_dice_rolled; num1++){
				//for(num2=0; num2<cur_dice_rolled; num2++){
				roll_results[num1] = lrand(&s) % 6 + 1;
			}
			for(num1=0; num1<cur_dice_rolled; num1++){
				if(roll_results[num1] == 1){
					roll_stats[cur_dice_rolled-1]++;
					break;
				}
				if(roll_results[num1] == 5){
					roll_stats[cur_dice_rolled-1]++;
					break;
				}
			}
			(void)memset(roll_results, '\0', 6);
		}
	}

	printf("max rolls: %u max dice: %u\n", max_rolls, max_dice_to_roll);
	printf("#dice\t%%\n");
	double calc1 = 0;
	for(cur_dice_rolled=1; cur_dice_rolled<=max_dice_to_roll; cur_dice_rolled++){
		calc1 = ((double)roll_stats[cur_dice_rolled-1]/max_rolls)*100;
		printf("%u\t%lf\n", cur_dice_rolled, calc1);
	}

	//unique combinations
	//calculate all permuations and subtract out the duplicates ...
	//(void)memset(roll_results, '\0', 6);
	//struct six{ char dice[6]; };
	struct Comb{
		char **dice;
		uint32_t total;
		//char dice[6];
	};
	uint32_t totals[6];
	struct Comb *comb = (struct Comb *)malloc(sizeof(struct Comb)*max_dice_to_roll);
	for(num1=0; num1<max_dice_to_roll; num1++){
		comb[num1].dice = (char **)malloc(sizeof(char *)*1);
		comb[num1].dice[0] = (char *)malloc(sizeof(char)*num1+1);
		for(num2=0; num2<num1+1; num2++){
			comb[num1].dice[0][num2] = 1;
			//comb[num1]->dice[0][num2] = (char *)malloc(sizeof(char)*num1+1);
		}
		comb[num1].total = 1;
	}

	//(void)memset(totals, sizeof(uint32_t)*6);
	//(void)memset(comb, sizeof(struct Comb)*1);

	//for(num1=0; num1<6; num1++){
	//	roll_results[num1] = 1;
		//for(num2=0; num2<6; num2++){
		//	comb[num1]->dice[num2] = 1;
		//}
	//}
	uint32_t digit_count = 0;
	uint32_t six_count = 0;
	uint32_t nums[6];
	uint32_t members_tmp = 1;
	uint32_t match = 0;
	char side_counts1[6];
	char side_counts2[6];
	(void)memset(roll_stats, '\0', sizeof(uint32_t)*max_dice_to_roll);
	for(cur_dice_rolled=0; cur_dice_rolled<max_dice_to_roll; cur_dice_rolled++){
		members_tmp = 1;
		//(void)memset(roll_results, '\0', sizeof(char)*6);
		for(num1=0; num1<6; num1++){
			roll_results[num1] = 1;
		}
		max_perm = pow(6, cur_dice_rolled);
for(cur_perm=0; cur_perm < max_perm; cur_perm++){
		for(digit_count = 0; digit_count<cur_dice_rolled+1; digit_count++){
			for(six_count = 0; six_count<6; six_count++){
				if(roll_results[digit_count] < 6){
					roll_results[digit_count]++;
					//continue;
				}else{
					//if(roll_results[digit_count] == 6)
					roll_results[digit_count] = 1;
				}
				

				//search all combs for match ignoring order ....
				match = 0;
				(void)memset(side_counts1, '\0', sizeof(char)*6);
				for(num1=0; num1<cur_dice_rolled+1; num1++){
					side_counts1[ (unsigned int)roll_results[num1] ]++;
				}
				for(num1=0; num1<members_tmp; num1++){
					(void)memset(side_counts2, '\0', sizeof(char)*6);
					//comb[cur_dice_rolled]->dice
					for(num2=0; num2<cur_dice_rolled+1; num2++){
						side_counts2[ (unsigned int)comb[cur_dice_rolled].dice[num1][num2] ]++;
						//side_counts2[num2]
					}
					for(num2=0; num2<cur_dice_rolled+1; num2++){
						if(side_counts1[num2] != side_counts2[num2]){
							match = 0;
							break;
						}
						if(num2 == cur_dice_rolled)
							match = 1;
					}
					if(match == 1)
						break;
				}

				if(!match){
					//printf("here 1\n");
					//FIXME: speedup later
					members_tmp++;
					if(comb[cur_dice_rolled].total < members_tmp){
						comb[cur_dice_rolled].total = members_tmp;
						comb[cur_dice_rolled].dice = (char **)realloc(comb[cur_dice_rolled].dice, members_tmp*sizeof(char *));
						comb[cur_dice_rolled].dice[members_tmp-1] = (char *)malloc(sizeof(char)*cur_dice_rolled+1);
					}
					for(num1=0; num1<cur_dice_rolled+1; num1++){
						comb[cur_dice_rolled].dice[members_tmp-1][num1] = roll_results[num1];
					}
				}
		//see if roll_results are unique
		//add to combinations list
		//increment roll_stats
			} //end of six count
		} //end of digit count
		printf("members: %u\n", members_tmp);
	} //end of max dice to roll count
	//print results
	printf("#dice:\tcombinations\n");
	for(num1=0; num1<max_dice_to_roll; num1++){
		printf("%u:\t%u\n", num1+1, comb[num1].total);
	}

	free(roll_stats);
	for(num1=0; num1<max_dice_to_roll; num1++){
		for(num2=0; num2 < comb[num1].total; num2++){
			free( comb[num1].dice[num2] );
		}
		free( comb[num1].dice );
	}
	free(comb);
	return 0;
}