// Copyright (c) 2023 Alex Diener. All rights reserved.

#include "PROJECT_NAME/EntityComponent_playerSteering.h"
#include "PROJECT_NAME/SharedDefinitions.h"

#define stemobject_implementation EntityComponent_playerSteering

stemobject_vtable_begin();
stemobject_vtable_entry(dispose);
stemobject_vtable_entry(initCopy);
stemobject_vtable_entry(getMoveVector);
stemobject_vtable_entry(startMoveInput);
stemobject_vtable_entry(stopMoveInput);
stemobject_vtable_entry(startActionInput);
stemobject_vtable_entry(stopActionInput);
stemobject_vtable_entry(cancelAllMoveInputs);
stemobject_vtable_entry(isTurnAdvancingInput);
stemobject_vtable_end();

bool EntityComponent_playerSteering_init(EntityComponent_playerSteering * self) {
	call_super(init, self);
	self->moveInput = MoveInputState_allNeutral;
	self->actionInput = ActionInputState_allNeutral;
	self->lastMoveAxis = MOVE_AXIS_X;
	return true;
}

void EntityComponent_playerSteering_dispose(EntityComponent_playerSteering * self) {
	call_super_virtual(dispose, self);
}

void EntityComponent_playerSteering_initCopy(EntityComponent_playerSteering * self, compat_type(GameEntityComponent *) originalUntyped) {
	call_super_virtual(initCopy, self, originalUntyped);
	EntityComponent_playerSteering * original = originalUntyped;
	self->moveInput = original->moveInput;
	self->actionInput = original->actionInput;
	self->lastMoveAxis = original->lastMoveAxis;
}

Vector2i EntityComponent_playerSteering_getMoveVector(EntityComponent_playerSteering * self, struct GameEntity * entity) {
	int directionX = MoveInput_mostRecentDirection(self->moveInput, MOVE_AXIS_X);
	int directionY = MoveInput_mostRecentDirection(self->moveInput, MOVE_AXIS_Y);
	if (directionX != 0 && directionY != 0) {
		if (self->lastMoveAxis == MOVE_AXIS_X) {
			directionY = 0;
		} else {
			directionX = 0;
		}
	}
	Vector2i moveVector = VECTOR2i(directionX, directionY);
	return moveVector;
}

bool EntityComponent_playerSteering_startMoveInput(EntityComponent_playerSteering * self, MoveInput_axis axis, MoveInput_direction direction) {
	bool changed = MoveInput_start(&self->moveInput, axis, direction);
	if (changed) {
		self->lastMoveAxis = axis;
	} else if (MoveInput_mostRecentDirection(self->moveInput, MOVE_AXIS_X) != MOVE_DIRECTION_NEUTRAL &&
	           MoveInput_mostRecentDirection(self->moveInput, MOVE_AXIS_Y) != MOVE_DIRECTION_NEUTRAL &&
	           axis != self->lastMoveAxis) {
		return false;
	}
	return changed;
}

bool EntityComponent_playerSteering_stopMoveInput(EntityComponent_playerSteering * self, MoveInput_axis axis, MoveInput_direction direction) {
	return MoveInput_stop(&self->moveInput, axis, direction);
}

bool EntityComponent_playerSteering_startActionInput(EntityComponent_playerSteering * self, ActionInput_action action) {
	return ActionInput_start(&self->actionInput, action);
}

bool EntityComponent_playerSteering_stopActionInput(EntityComponent_playerSteering * self, ActionInput_action action) {
	return ActionInput_stop(&self->actionInput, action);
}

void EntityComponent_playerSteering_cancelAllMoveInputs(EntityComponent_playerSteering * self) {
	self->moveInput = MoveInputState_allNeutral;
}

bool EntityComponent_playerSteering_isTurnAdvancingInput(EntityComponent_playerSteering * self, MoveInput_axis axis, MoveInput_direction direction) {
	if (axis == self->lastMoveAxis && MoveInput_mostRecentDirection(self->moveInput, axis) == direction) {
		return true;
	}
	if (axis != self->lastMoveAxis && MoveInput_mostRecentDirection(self->moveInput, self->lastMoveAxis) == MOVE_DIRECTION_NEUTRAL) {
		return true;
	}
	return false;
}
