#include "document/DocumentList.h"
#include "unittest/TestSuite.h"

static void testInit(void) {
	DocumentList * list = DocumentList_create();
	TestCase_assertUIntEqual(list->documentCount, 0);
	TestCase_assertPointerNULL(list->documents);
	DocumentList_dispose(list);
}

static void testAddRemove(void) {
	DocumentList * list = DocumentList_create();
	const char * document1Name = "a";
	DocumentList_addDocument(list, document1Name, 0);
	TestCase_assertUIntEqual(list->documentCount, 1);
	TestCase_assertPointerNonNULL(list->documents);
	TestCase_assertStringEqual(list->documents[0].filePath, "a");
	TestCase_assertPointerUnequal(list->documents[0].filePath, document1Name);
	
	DocumentList_addDocument(list, "b", 0);
	TestCase_assertUIntEqual(list->documentCount, 2);
	TestCase_assertStringEqual(list->documents[0].filePath, "a");
	TestCase_assertStringEqual(list->documents[1].filePath, "b");
	
	DocumentList_addDocument(list, "a", 0);
	TestCase_assertUIntEqual(list->documentCount, 2);
	TestCase_assertStringEqual(list->documents[0].filePath, "b");
	TestCase_assertStringEqual(list->documents[1].filePath, "a");
	
	DocumentList_addDocument(list, "c", 0);
	TestCase_assertUIntEqual(list->documentCount, 3);
	TestCase_assertStringEqual(list->documents[0].filePath, "b");
	TestCase_assertStringEqual(list->documents[1].filePath, "a");
	TestCase_assertStringEqual(list->documents[2].filePath, "c");
	
	DocumentList_addDocument(list, "b", 0);
	TestCase_assertUIntEqual(list->documentCount, 3);
	TestCase_assertStringEqual(list->documents[0].filePath, "a");
	TestCase_assertStringEqual(list->documents[1].filePath, "c");
	TestCase_assertStringEqual(list->documents[2].filePath, "b");
	
	DocumentList_addDocument(list, "c", 0);
	TestCase_assertUIntEqual(list->documentCount, 3);
	TestCase_assertStringEqual(list->documents[0].filePath, "a");
	TestCase_assertStringEqual(list->documents[1].filePath, "b");
	TestCase_assertStringEqual(list->documents[2].filePath, "c");
	
	DocumentList_removeDocumentWithFilePath(list, "a");
	TestCase_assertUIntEqual(list->documentCount, 2);
	TestCase_assertStringEqual(list->documents[0].filePath, "b");
	TestCase_assertStringEqual(list->documents[1].filePath, "c");
	
	DocumentList_removeDocumentWithFilePath(list, "c");
	TestCase_assertUIntEqual(list->documentCount, 1);
	TestCase_assertStringEqual(list->documents[0].filePath, "b");
	
	DocumentList_removeDocumentWithFilePath(list, "a");
	TestCase_assertUIntEqual(list->documentCount, 1);
	TestCase_assertStringEqual(list->documents[0].filePath, "b");
	
	DocumentList_removeDocumentWithFilePath(list, "b");
	TestCase_assertUIntEqual(list->documentCount, 0);
	
	DocumentList_addDocument(list, "a", 0);
	DocumentList_addDocument(list, "b", 0);
	DocumentList_addDocument(list, "c", 0);
	DocumentList_removeDocumentAtIndex(list, 1);
	TestCase_assertUIntEqual(list->documentCount, 2);
	TestCase_assertStringEqual(list->documents[0].filePath, "a");
	TestCase_assertStringEqual(list->documents[1].filePath, "c");
	
	DocumentList_removeDocumentAtIndex(list, 2);
	TestCase_assertUIntEqual(list->documentCount, 2);
	TestCase_assertStringEqual(list->documents[0].filePath, "a");
	TestCase_assertStringEqual(list->documents[1].filePath, "c");
	
	DocumentList_removeDocumentAtIndex(list, 1);
	TestCase_assertUIntEqual(list->documentCount, 1);
	TestCase_assertStringEqual(list->documents[0].filePath, "a");
	
	DocumentList_removeDocumentAtIndex(list, 0);
	TestCase_assertUIntEqual(list->documentCount, 0);
	
	DocumentList_addDocument(list, "a", 0);
	DocumentList_addDocument(list, "b", 0);
	DocumentList_addDocument(list, "c", 0);
	DocumentList_removeAllDocuments(list);
	TestCase_assertUIntEqual(list->documentCount, 0);
	
	DocumentList_dispose(list);
}

static void testPruneWhileAdding(void) {
	DocumentList * list = DocumentList_create();
	DocumentList_addDocument(list, "a", 3);
	DocumentList_addDocument(list, "b", 3);
	DocumentList_addDocument(list, "c", 3);
	TestCase_assertUIntEqual(list->documentCount, 3);
	TestCase_assertStringEqual(list->documents[0].filePath, "a");
	TestCase_assertStringEqual(list->documents[1].filePath, "b");
	TestCase_assertStringEqual(list->documents[2].filePath, "c");
	
	DocumentList_addDocument(list, "d", 3);
	TestCase_assertUIntEqual(list->documentCount, 3);
	TestCase_assertStringEqual(list->documents[0].filePath, "b");
	TestCase_assertStringEqual(list->documents[1].filePath, "c");
	TestCase_assertStringEqual(list->documents[2].filePath, "d");
	
	DocumentList_addDocument(list, "d", 2);
	TestCase_assertUIntEqual(list->documentCount, 2);
	TestCase_assertStringEqual(list->documents[0].filePath, "c");
	TestCase_assertStringEqual(list->documents[1].filePath, "d");
	
	DocumentList_addDocument(list, "a", 1);
	TestCase_assertUIntEqual(list->documentCount, 1);
	TestCase_assertStringEqual(list->documents[0].filePath, "a");
	
	DocumentList_dispose(list);
}

static void testPruneToCount(void) {
	DocumentList * list = DocumentList_create();
	DocumentList_addDocument(list, "a", 0);
	DocumentList_addDocument(list, "b", 0);
	DocumentList_addDocument(list, "c", 0);
	DocumentList_pruneToCount(list, 3);
	TestCase_assertUIntEqual(list->documentCount, 3);
	TestCase_assertStringEqual(list->documents[0].filePath, "a");
	TestCase_assertStringEqual(list->documents[1].filePath, "b");
	TestCase_assertStringEqual(list->documents[2].filePath, "c");
	
	DocumentList_pruneToCount(list, 2);
	TestCase_assertUIntEqual(list->documentCount, 2);
	TestCase_assertStringEqual(list->documents[0].filePath, "b");
	TestCase_assertStringEqual(list->documents[1].filePath, "c");
	
	DocumentList_addDocument(list, "a", 0);
	DocumentList_pruneToCount(list, 1);
	TestCase_assertUIntEqual(list->documentCount, 1);
	TestCase_assertStringEqual(list->documents[0].filePath, "a");
	
	DocumentList_dispose(list);
}

static void testReorderDocument(void) {
	DocumentList * list = DocumentList_create();
	DocumentList_addDocument(list, "a", 0);
	DocumentList_addDocument(list, "b", 0);
	DocumentList_addDocument(list, "c", 0);
	DocumentList_reorderDocument(list, 0, 2);
	TestCase_assertStringEqual(list->documents[0].filePath, "b");
	TestCase_assertStringEqual(list->documents[1].filePath, "c");
	TestCase_assertStringEqual(list->documents[2].filePath, "a");
	
	DocumentList_reorderDocument(list, 1, 2);
	TestCase_assertStringEqual(list->documents[0].filePath, "b");
	TestCase_assertStringEqual(list->documents[1].filePath, "a");
	TestCase_assertStringEqual(list->documents[2].filePath, "c");
	
	DocumentList_reorderDocument(list, 1, 0);
	TestCase_assertStringEqual(list->documents[0].filePath, "a");
	TestCase_assertStringEqual(list->documents[1].filePath, "b");
	TestCase_assertStringEqual(list->documents[2].filePath, "c");
	
	DocumentList_reorderDocument(list, 2, 0);
	TestCase_assertStringEqual(list->documents[0].filePath, "c");
	TestCase_assertStringEqual(list->documents[1].filePath, "a");
	TestCase_assertStringEqual(list->documents[2].filePath, "b");
	
	DocumentList_dispose(list);
}

static void testValidateFilesExist(void) {
	DocumentList * list = DocumentList_create();
	DocumentList_addDocument(list, "not a valid file path", 0);
	DocumentList_addDocument(list, "emptyfile", 0);
	TestCase_assertBoolFalse(list->documents[0].fileExists);
	TestCase_assertBoolFalse(list->documents[1].fileExists);
	
	DocumentList_validateFilesExist(list);
	TestCase_assertBoolFalse(list->documents[0].fileExists);
	TestCase_assertBoolTrue(list->documents[1].fileExists);
	
	list->documents[0].fileExists = true;
	DocumentList_validateFilesExist(list);
	TestCase_assertBoolFalse(list->documents[0].fileExists);
	TestCase_assertBoolTrue(list->documents[1].fileExists);
	
	DocumentList_dispose(list);
}

TEST_SUITE(DocumentListTest,
           testInit,
           testAddRemove,
           testPruneWhileAdding,
           testPruneToCount,
           testReorderDocument,
           testValidateFilesExist)
