#include "FixedArrayList.h"
#include "SinglyLinkedList.h"
#include "HybridIterator.h"

#include "FixedMap.h"

#include <stdio.h>

/*

class Packet: public SinglyLinkedList {
public:
	SinglyLinkedList::Element<uint32_t> element1;
	SinglyLinkedList::Element<uint32_t> element2;

	Packet() {
		this->start = &element1;
		element1.next = &element2;
	}
};

class Packet2: public SinglyLinkedList {
public:
	SinglyLinkedList::Element<uint32_t> element1;
	SinglyLinkedList::Element<FixedArrayList<FixedArrayList<uint8_t, 5>, 2>> element2;
	SinglyLinkedList::Element<uint32_t> element3;

	Packet2() {
		this->start = &element1;
		element1.next = &element2;
		element2.next = &element3;
	}
};

class Packet3: public SinglyLinkedList {
public:
	SinglyLinkedList::TypedElement<uint32_t> element1;
	SinglyLinkedList::TypedElement<uint32_t> element2;

	Packet3() {
		this->start = &element1;
		element1.next = &element2;
	}
};

void arrayList() {
	puts("** Array List **");
	FixedArrayList<uint32_t, 10, uint32_t> list;
	FixedArrayList<uint32_t, 10, uint32_t> list2;

	list.size = 2;

	list[0] = 0xcafecafe;

	list[1] = 0x12345678;

	uint8_t buffer[100];
	uint8_t *pointer = buffer;
	uint32_t size = 0;
	uint32_t maxSize = 100;
	uint32_t i;
	int32_t size2;

	printf("printsize: %i\n", list.getPrintSize());

	list.print(&pointer, &size, 100, true);

	printf("buffer(%i):", size);
	for (i = 0; i < size; ++i) {
		printf("%02x", buffer[i]);
	}
	printf("\n");

	pointer = buffer;

	size2 = size;

	printf("list2 read: %x\n", list2.read(&pointer, &size2, true));

	printf("list2(%i):", list2.size);
	for (ArrayList<uint32_t, uint32_t>::Iterator iter = list2.begin();
			iter != list2.end(); iter++) {
		printf("0x%04x ", *iter);
	}
	printf("\n");

	HybridIterator<uint32_t, uint32_t> hiter(list.begin(),list.end());

	printf("hybrid1: 0x%04x\n", *(hiter++));
	printf("hybrid2: 0x%04x\n", *hiter);

}

void allocatingList() {
	puts("** Allocating List **");
	ArrayList<uint8_t> myList(3), myList2(2);
	myList[0] = 0xab;
	myList[1] = 0xcd;
	myList.size = 2;

	uint8_t buffer[100];
	uint8_t *pointer = buffer;
	uint32_t size = 0;
	uint32_t maxSize = 100;
	uint32_t i;
	int32_t size2;

	myList.print(&pointer, &size, 100, true);

	pointer = buffer;
	size2 = size;

	printf("Read %x\n", myList2.read(&pointer, &size2, true));

	printf("%x,%x\n", myList2[0], myList2[1]);

}

void linkedList() {
	puts("** Linked List **");
	uint8_t buffer[100];
	uint8_t *pointer = buffer;
	uint32_t size = 0;
	uint32_t maxSize = 100;
	uint32_t i;
	int32_t size2;

	Packet myPacket;
	myPacket.element1.entry = 0x12345678;
	myPacket.element2.entry = 0x9abcdef0;

	pointer = buffer;
	size = 0;
	ReturnValue_t result = myPacket.print(&pointer, &size, 100, true);

	printf("result %02x\n", result);

	printf("printsize: %i\n", myPacket.getPrintSize());

	printf("buffer(%i):", size);
	for (i = 0; i < size; ++i) {
		printf("%02x", buffer[i]);
	}
	printf("\n");

	Packet3 myPacket3;

	myPacket3.element1.entry = 0x12345678;
	myPacket3.element2.entry = 0xabcdeff;

	SinglyLinkedList::TypedIterator<uint32_t> titer(&myPacket3.element1);

	printf("0x%04x\n", *titer);

	HybridIterator<uint32_t, uint32_t> hiter(&myPacket3.element1);

	printf("hybrid1: 0x%04x\n", *hiter);
	hiter++;
	printf("hybrid2: 0x%04x\n", *hiter);
}

void complex() {
	puts("** complex **");
	uint8_t buffer[100];
	uint8_t *pointer = buffer;
	uint32_t size = 0;
	uint32_t maxSize = 100;
	uint32_t i;
	int32_t size2 = size;

	Packet myPacket2;

	size2 = size;
	pointer = buffer;

	myPacket2.read(&pointer, &size2, true);

	printf("packet: 0x%04x, 0x%04x\n", myPacket2.element1.entry,
			myPacket2.element2.entry);

	buffer[0] = 0x12;
	buffer[1] = 0x34;
	buffer[2] = 0x56;
	buffer[3] = 0x78;
	buffer[4] = 0x2;
	buffer[5] = 0x3;
	buffer[6] = 0xab;
	buffer[7] = 0xcd;
	buffer[8] = 0xef;
	buffer[9] = 0x2;
	buffer[10] = 0x11;
	buffer[11] = 0x22;
	buffer[12] = 0xca;
	buffer[13] = 0xfe;
	buffer[14] = 0x5a;
	buffer[15] = 0xfe;

	pointer = buffer;
	size2 = 23;

	Packet2 p2;

	ReturnValue_t result = p2.read(&pointer, &size2, true);
	printf("result is %02x\n", result);

	printf("%04x; %i: %i: %x %x %x; %i: %x %x;; %04x\n", p2.element1.entry,
			p2.element2.entry.size, p2.element2.entry[0].size,
			p2.element2.entry[0][0], p2.element2.entry[0][1],
			p2.element2.entry[0][2], p2.element2.entry[1].size,
			p2.element2.entry[1][0], p2.element2.entry[1][1],
			p2.element3.entry);

}
*/
struct Test {
	uint32_t a;
	uint32_t b;
};

template<typename key_t, typename T>
void printMap(FixedMap<key_t, T> *map) {
	typename FixedMap<key_t, T>::Iterator iter;
	printf("Map (%i): ", map->getSize());
	for (iter = map->begin(); iter != map->end(); ++iter) {
		printf("%x:%08x,%08x ", iter.value->first, (*iter).a, (*iter).b);
	}
	printf("\n");
}

template<typename T>
void map() {
	puts("** Map **");
	typename FixedMap<T, Test>::Iterator iter;
	ReturnValue_t result;
	FixedMap<T, Test> myMap(5);

	printMap<T, Test>(&myMap);

	Test a;
	a.a = 0x01234567;
	a.b = 0xabcdef89;

	myMap.insert(1, a);
	printMap<T, Test>(&myMap);

	a.a = 0;

	myMap.insert(2, a);
	printMap<T, Test>(&myMap);

	printf("2 exists: %x\n", myMap.exists(0x02));

	printf("ff exists: %x\n", myMap.exists(0xff));

	a.a = 1;
	printf("insert 0x2: %x\n", myMap.insert(2, a));

	result = myMap.insert(0xff, a);
	a.a = 0x44;
	result = myMap.insert(0xab, a);
	result = myMap.insert(0xa, a);

	printMap<T, Test>(&myMap);

	printf("insert 0x5: %x\n", myMap.insert(5, a));

	printf("erase 0xfe: %x\n", myMap.erase(0xfe));

	printf("erase 0x2: %x\n", myMap.erase(0x2));

	printMap<T, Test>(&myMap);

	printf("erase 0xab: %x\n", myMap.erase(0xab));
	printMap<T, Test>(&myMap);

	printf("insert 0x5: %x\n", myMap.insert(5, a));
	printMap<T, Test>(&myMap);

	iter = myMap.begin();
	++iter;
	++iter;
	++iter;

	printf("iter: %i: %x,%x\n",iter.value->first, iter->a, iter->b);

	myMap.erase(&iter);

	printf("iter: %i: %x,%x\n",iter.value->first, iter->a, iter->b);
	printMap<T, Test>(&myMap);

}

/*
void mapPrint() {
	puts("** Map Print **");
	FixedMap<uint16_t, Packet2> myMap(5);
	Packet2 myPacket;
	myPacket.element1.entry = 0x12345678;

	myPacket.element2.entry[0][0] = 0xab;
	myPacket.element2.entry[0][1] = 0xcd;
	myPacket.element2.entry[0].size = 2;
	myPacket.element2.entry.size = 1;

	myPacket.element3.entry = 0xabcdef90;

	myMap.insert(0x1234, myPacket);

	uint8_t buffer[100];
	uint32_t size = 0, i;
	uint8_t *pointer = buffer;

	printf("printsize: %i\n", myMap.getPrintSize());

	SerializeAdapter<FixedMap<uint16_t, Packet2>>::print(&myMap, &pointer,
			&size, 100, false);

	printf("buffer(%i):", size);
	for (i = 0; i < size; ++i) {
		printf("%02x", buffer[i]);
	}
	printf("\n");

	int32_t size2 = size;
	pointer = buffer;

	FixedMap<uint16_t, Packet2> myMap2(5);

	ReturnValue_t result = SerializeAdapter<FixedMap<uint16_t, Packet2>>::read(
			&myMap2, &pointer, &size2, false);

	Packet2 *myPacket2 = myMap2.find(0x1234);

	printf("Map (%i): Packet2: %x, Array (%i): Array (%i): %x, %x; %x\n",
			myMap2.getSize(), myPacket2->element1.entry,
			myPacket2->element2.entry.size, myPacket2->element2.entry[0].size,
			myPacket2->element2.entry[0][0], myPacket2->element2.entry[0][1],
			myPacket2->element3.entry);

}

void empty() {
	puts("** Empty **");
	ArrayList<uint32_t> list(0);
	printf("%p %p\n", list.front(), list.back());
}
*/

int main(void) {

//	arrayList();
//	linkedList();
//	allocatingList();
//	complex();

	map<uint32_t>();
//
//	mapPrint();

//	empty();



	return 0;
}