#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>


#include "CUnit/Basic.h"
#include "PriorityQueue.h"

#ifndef DEBUG
#define DEBUG
#endif

static PrioQueueStruc *Q; 
static char *first,*second,*third;

int init_suite (void) {
	if (NULL == (Q= makePrioQ())) return -1;
	else return 0;
}

int clean_suite (void) {
	return 0;
}

void testInsertAElement (void) {
	
	first= malloc(3*sizeof(char));
	first= "foo";

	printf("SIZE = %d | ",Q->size);
	printf("MAXSIZE = %d | ",Q->maxSize);
	CU_ASSERT(true == insertPrioQ(first,0,Q));
	printPrioQ(Q);
	printf("SIZE = %d | ",Q->size);
	printf("MAXSIZE = %d | ",Q->maxSize);
}

void testInsertOneElement (void) {
	
	first= malloc(3*sizeof(char));
	first= "ten";

	CU_ASSERT(true == insertPrioQ(first,10,Q));
	printPrioQ(Q);
}

void testPopOneElement (void) {
	popPrioQ(Q);
}

void testInsertSorted (void) {
	second= malloc(4*sizeof(char));
	second= "five";
	
	CU_ASSERT(true == insertPrioQ(second,5,Q));
	printPrioQ(Q);
}

void testInsertAndHeapify (void) {
	third= malloc(6*sizeof(char));
	third= "twenty";

	CU_ASSERT(true == insertPrioQ(third,20,Q));
	printPrioQ(Q);
}

void testGetFirstElement (void) {
	void* elem;

	elem= getFirstPrioQ(Q);
	CU_ASSERT(elem == third);
	printPrioQ(Q);
}

void testSwap (void) {
	swap(Q,0,2);
	printPrioQ(Q);
	swap(Q,2,0);
	printPrioQ(Q);
}

void testPop (void) {
	void *elem;
	
	elem= popPrioQ(Q);
	CU_ASSERT(elem == third);
	printPrioQ(Q);
	printf("size = %d",Q->size);
	elem= popPrioQ(Q);
	CU_ASSERT(elem == first);
	printPrioQ(Q);
	printf("size = %d",Q->size);
	elem= popPrioQ(Q);
	CU_ASSERT(elem == second);
	printPrioQ(Q);
	printf("size = %d",Q->size);
}

void testPopEmptyQueue (void) {
	void *elem;
	CU_ASSERT (NULL == (elem= popPrioQ(Q)));
}

void testEnlargeQueue (void) {
	int i;
	char *elem;
	for (i= 0; i<1163; i++) {
		elem= malloc(5*sizeof(char));
		sprintf(elem,"%d",i);
		CU_ASSERT(true == insertPrioQ(elem,i,Q));
	}
}


void testPopEnlargedQueue (void) {
	int i;
	char *elem; 
	for (i= 1162; i>= 0; i--) {
		elem= popPrioQ(Q);
		CU_ASSERT(i == atoi(elem));
	}
	CU_ASSERT(NULL == popPrioQ(Q));
}

int main () {
	CU_pSuite pSuite= NULL;

	if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();

	pSuite= CU_add_suite("Simple Test Suite",init_suite, clean_suite);
	if (NULL == pSuite) {
		CU_cleanup_registry();
		return CU_get_error();
	}

	if (NULL == CU_add_test(pSuite,"test of insert first element",testInsertOneElement) ||
		NULL == CU_add_test(pSuite,"test of insert sorted",testInsertSorted) ||
		NULL == CU_add_test(pSuite,"test of insert and heapify",testInsertAndHeapify) ||
		NULL == CU_add_test(pSuite,"test of swap",testSwap) ||
		NULL == CU_add_test(pSuite,"test of get top element",testGetFirstElement) ||
		NULL == CU_add_test(pSuite,"test of pop elements",testPop) || 
		NULL == CU_add_test(pSuite,"test of pop an empty queue",testPopEmptyQueue) || 
	    NULL == CU_add_test(pSuite,"test of again a element",testInsertAElement) ||
	    NULL == CU_add_test(pSuite,"test of remove the element",testPopOneElement) ||
		NULL == CU_add_test(pSuite,"test of enlarge queue",testEnlargeQueue) || 
		NULL == CU_add_test(pSuite,"test of pop enlarged queue",testPopEnlargedQueue)) {



		CU_cleanup_registry();
		return CU_get_error();
	}
	

	CU_basic_set_mode(CU_BRM_VERBOSE);
	CU_basic_run_tests();
	CU_cleanup_registry();
	return CU_get_error();
}
