#include "gamemath/MoveInput.h"
#include "unittest/TestSuite.h"

static void testIsInput(void) {
	MoveInputState state = MoveInputState_allNeutral;
	
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, -1));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, 1));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_Y, -1));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_Y, 1));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_Z, -1));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_Z, 1));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_PITCH, -1));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_PITCH, 1));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_YAW, -1));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_YAW, 1));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_ROLL, -1));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_ROLL, 1));
	
	MoveInput_start(&state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE);
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE));
	
	MoveInput_start(&state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE);
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE));
	
	MoveInput_stop(&state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE);
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE));
	
	MoveInput_stop(&state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE);
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE));
	
	MoveInput_stop(&state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE);
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE));
	
	MoveInput_start(&state, MOVE_AXIS_Y, MOVE_DIRECTION_NEGATIVE);
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_Y, MOVE_DIRECTION_NEGATIVE));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_Y, MOVE_DIRECTION_POSITIVE));
	
	MoveInput_start(&state, MOVE_AXIS_Y, MOVE_DIRECTION_NEGATIVE);
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_Y, MOVE_DIRECTION_NEGATIVE));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_Y, MOVE_DIRECTION_POSITIVE));
	
	state = MoveInputState_allNeutral;
	MoveInput_start(&state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE);
	MoveInput_start(&state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE);
	MoveInput_start(&state, MOVE_AXIS_Y, MOVE_DIRECTION_NEGATIVE);
	MoveInput_start(&state, MOVE_AXIS_Y, MOVE_DIRECTION_POSITIVE);
	MoveInput_start(&state, MOVE_AXIS_Z, MOVE_DIRECTION_NEGATIVE);
	MoveInput_start(&state, MOVE_AXIS_Z, MOVE_DIRECTION_POSITIVE);
	MoveInput_start(&state, MOVE_AXIS_PITCH, MOVE_DIRECTION_NEGATIVE);
	MoveInput_start(&state, MOVE_AXIS_PITCH, MOVE_DIRECTION_POSITIVE);
	MoveInput_start(&state, MOVE_AXIS_YAW, MOVE_DIRECTION_NEGATIVE);
	MoveInput_start(&state, MOVE_AXIS_YAW, MOVE_DIRECTION_POSITIVE);
	MoveInput_start(&state, MOVE_AXIS_ROLL, MOVE_DIRECTION_NEGATIVE);
	MoveInput_start(&state, MOVE_AXIS_ROLL, MOVE_DIRECTION_POSITIVE);
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_X, -1));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_X, 1));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_Y, -1));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_Y, 1));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_Z, -1));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_Z, 1));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_PITCH, -1));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_PITCH, 1));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_YAW, -1));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_YAW, 1));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_ROLL, -1));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_ROLL, 1));
}

static void testCombinedDirection(void) {
	MoveInputState state = MoveInputState_allNeutral;
	
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_X), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_Y), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_Z), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_YAW), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_ROLL), MOVE_DIRECTION_NEUTRAL);
	
	MoveInput_start(&state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_X), MOVE_DIRECTION_NEGATIVE);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_Y), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_Z), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_YAW), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_ROLL), MOVE_DIRECTION_NEUTRAL);
	
	MoveInput_start(&state, MOVE_AXIS_Z, MOVE_DIRECTION_POSITIVE);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_X), MOVE_DIRECTION_NEGATIVE);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_Y), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_Z), MOVE_DIRECTION_POSITIVE);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_YAW), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_ROLL), MOVE_DIRECTION_NEUTRAL);
	
	MoveInput_start(&state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_X), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_Y), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_Z), MOVE_DIRECTION_POSITIVE);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_YAW), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_ROLL), MOVE_DIRECTION_NEUTRAL);
	
	MoveInput_stop(&state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_X), MOVE_DIRECTION_NEGATIVE);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_Y), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_Z), MOVE_DIRECTION_POSITIVE);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_YAW), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_combinedDirection(state, MOVE_AXIS_ROLL), MOVE_DIRECTION_NEUTRAL);
}

static void testMostRecentDirection(void) {
	MoveInputState state = MoveInputState_allNeutral;
	
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_X), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_Y), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_Z), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_YAW), MOVE_DIRECTION_NEUTRAL);
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_ROLL), MOVE_DIRECTION_NEUTRAL);
	
	MoveInput_start(&state, MOVE_AXIS_PITCH, MOVE_DIRECTION_POSITIVE);
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_POSITIVE);
	
	MoveInput_start(&state, MOVE_AXIS_PITCH, MOVE_DIRECTION_NEGATIVE);
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_NEGATIVE);
	
	MoveInput_stop(&state, MOVE_AXIS_PITCH, MOVE_DIRECTION_NEGATIVE);
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_POSITIVE);
	
	MoveInput_start(&state, MOVE_AXIS_PITCH, MOVE_DIRECTION_NEGATIVE);
	MoveInput_stop(&state, MOVE_AXIS_PITCH, MOVE_DIRECTION_POSITIVE);
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_NEGATIVE);
	
	MoveInput_start(&state, MOVE_AXIS_PITCH, MOVE_DIRECTION_POSITIVE);
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_POSITIVE);
	
	MoveInput_stop(&state, MOVE_AXIS_PITCH, MOVE_DIRECTION_POSITIVE);
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_NEGATIVE);
	
	MoveInput_stop(&state, MOVE_AXIS_PITCH, MOVE_DIRECTION_NEGATIVE);
	TestCase_assertIntEqual(MoveInput_mostRecentDirection(state, MOVE_AXIS_PITCH), MOVE_DIRECTION_NEUTRAL);
}

static void testReturnValue(void) {
	MoveInputState state = MoveInputState_allNeutral;
	bool result;
	
	result = MoveInput_start(&state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE);
	TestCase_assertBoolTrue(result);
	result = MoveInput_start(&state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE);
	TestCase_assertBoolFalse(result);
	
	result = MoveInput_start(&state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE);
	TestCase_assertBoolTrue(result);
	result = MoveInput_stop(&state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE);
	TestCase_assertBoolTrue(result);
	result = MoveInput_stop(&state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE);
	TestCase_assertBoolTrue(result);
	result = MoveInput_stop(&state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE);
	TestCase_assertBoolFalse(result);
}

static void testClear(void) {
	MoveInputState state = MoveInputState_allNeutral;
	
	MoveInput_start(&state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE);
	MoveInput_start(&state, MOVE_AXIS_Y, MOVE_DIRECTION_NEGATIVE);
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_Y, MOVE_DIRECTION_NEGATIVE));
	
	MoveInput_clear(&state, MOVE_AXIS_X);
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE));
	TestCase_assertBoolTrue(MoveInput_isInput(state, MOVE_AXIS_Y, MOVE_DIRECTION_NEGATIVE));
	
	MoveInput_clear(&state, MOVE_AXIS_Y);
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_POSITIVE));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_X, MOVE_DIRECTION_NEGATIVE));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_Y, MOVE_DIRECTION_POSITIVE));
	TestCase_assertBoolFalse(MoveInput_isInput(state, MOVE_AXIS_Y, MOVE_DIRECTION_NEGATIVE));
}

TEST_SUITE(MoveInputTest,
           testIsInput,
           testCombinedDirection,
           testMostRecentDirection,
           testReturnValue,
           testClear)
