#include "utilities/IndexPairSelection.h"
#include "unittest/TestSuite.h"
#include <limits.h>

static void testInit(void) {
	IndexPairSelection * selection = IndexPairSelection_create(false, 3);
	TestCase_assertUIntEqual(selection->pairCount, 0);
	TestCase_assertPointerNULL(selection->pairs);
	IndexPairSelection_dispose(selection);
}

static void testBasicOperations(void) {
	IndexPairSelection * selection = IndexPairSelection_create(false, 3);
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 0, 1));
	TestCase_assertBoolTrue(IndexPairSelection_selectIndexPair(selection, 0, 1));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 0, 1));
	TestCase_assertBoolFalse(IndexPairSelection_selectIndexPair(selection, 0, 1));
	
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 1, 2));
	TestCase_assertBoolTrue(IndexPairSelection_selectIndexPair(selection, 1, 2));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 1, 2));
	
	TestCase_assertBoolFalse(IndexPairSelection_deselectIndexPair(selection, 2, 3));
	IndexPairSelection_selectIndexPair(selection, 2, 3);
	TestCase_assertBoolTrue(IndexPairSelection_deselectIndexPair(selection, 2, 3));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 2, 3));
	
	TestCase_assertBoolFalse(IndexPairSelection_toggleIndexPair(selection, 0, 1));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 0, 1));
	
	TestCase_assertBoolTrue(IndexPairSelection_toggleIndexPair(selection, 2, 4));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 2, 4));
	
	TestCase_assertBoolTrue(IndexPairSelection_truncateToMaxIndex(selection, 3));
	TestCase_assertUIntEqual(selection->pairCount, 1);
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 1, 2));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 2, 4));
	
	TestCase_assertBoolTrue(IndexPairSelection_deselectAll(selection));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 1, 2));
	TestCase_assertUIntEqual(selection->pairCount, 0);
	
	TestCase_assertBoolFalse(IndexPairSelection_deselectAll(selection));
	IndexPairSelection_dispose(selection);
}

static void testCopy(void) {
	IndexPairSelection * selection = IndexPairSelection_create(false, 3);
	IndexPairSelection * copy = IndexPairSelection_copy(selection);
	IndexPairSelection_dispose(selection);
	
	TestCase_assertUIntEqual(copy->pairCount, 0);
	TestCase_assertPointerNULL(copy->pairs);
	IndexPairSelection_dispose(copy);
	
	selection = IndexPairSelection_create(false, 3);
	IndexPairSelection_selectIndexPair(selection, 1, 2);
	IndexPairSelection_selectIndexPair(selection, 3, 5);
	copy = IndexPairSelection_copy(selection);
	IndexPairSelection_dispose(selection);
	
	TestCase_assertUIntEqual(copy->pairCount, 2);
	TestCase_assertPointerNonNULL(copy->pairs);
	TestCase_assertUIntEqual(copy->pairs[0].index0, 1);
	TestCase_assertUIntEqual(copy->pairs[0].index1, 2);
	TestCase_assertUIntEqual(copy->pairs[1].index0, 3);
	TestCase_assertUIntEqual(copy->pairs[1].index1, 5);
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(copy, 0, 1));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(copy, 1, 2));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(copy, 2, 3));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(copy, 3, 5));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(copy, 4, 5));
	
	IndexPairSelection * copy2 = IndexPairSelection_create(false, 3);
	IndexPairSelection_copySelectionFrom(copy2, copy);
	IndexPairSelection_dispose(copy);
	
	TestCase_assertUIntEqual(copy2->pairCount, 2);
	TestCase_assertPointerNonNULL(copy2->pairs);
	TestCase_assertUIntEqual(copy2->pairs[0].index0, 1);
	TestCase_assertUIntEqual(copy2->pairs[0].index1, 2);
	TestCase_assertUIntEqual(copy2->pairs[1].index0, 3);
	TestCase_assertUIntEqual(copy2->pairs[1].index1, 5);
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(copy2, 1, 2));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(copy2, 3, 5));
	IndexPairSelection_dispose(copy2);
}

static void testOrderedPairs(void) {
	IndexPairSelection * selection = IndexPairSelection_create(false, 3);
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 0, 1));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 1, 0));
	TestCase_assertBoolTrue(IndexPairSelection_selectIndexPair(selection, 0, 1));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 0, 1));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 1, 0));
	TestCase_assertBoolFalse(IndexPairSelection_selectIndexPair(selection, 1, 0));
	
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 3, 2));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 2, 3));
	TestCase_assertBoolTrue(IndexPairSelection_selectIndexPair(selection, 3, 2));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 3, 2));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 2, 3));
	TestCase_assertBoolFalse(IndexPairSelection_selectIndexPair(selection, 2, 3));
	
	TestCase_assertBoolTrue(IndexPairSelection_selectIndexPair(selection, 3, 4));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 3, 4));
	IndexPairSelection_truncateToMaxIndex(selection, 3);
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 0, 1));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 2, 3));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 3, 4));
	TestCase_assertUIntEqual(selection->pairCount, 1);
	IndexPairSelection_dispose(selection);
	
	selection = IndexPairSelection_create(true, 3);
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 0, 1));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 1, 0));
	TestCase_assertBoolTrue(IndexPairSelection_selectIndexPair(selection, 0, 1));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 0, 1));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 1, 0));
	TestCase_assertBoolTrue(IndexPairSelection_selectIndexPair(selection, 1, 0));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 1, 0));
	
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 3, 2));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 2, 3));
	TestCase_assertBoolTrue(IndexPairSelection_selectIndexPair(selection, 3, 2));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 3, 2));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 2, 3));
	TestCase_assertBoolTrue(IndexPairSelection_selectIndexPair(selection, 2, 3));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 2, 3));
	
	TestCase_assertBoolTrue(IndexPairSelection_selectIndexPair(selection, 3, 4));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 3, 4));
	IndexPairSelection_truncateToMaxIndex(selection, 3);
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 0, 1));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 1, 0));
	TestCase_assertBoolTrue(IndexPairSelection_isPairSelected(selection, 2, 3));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 3, 2));
	TestCase_assertBoolFalse(IndexPairSelection_isPairSelected(selection, 3, 4));
	TestCase_assertUIntEqual(selection->pairCount, 3);
	IndexPairSelection_dispose(selection);
}

TEST_SUITE(IndexPairSelectionTest,
           testInit,
           testBasicOperations,
           testCopy,
           testOrderedPairs)
