#include "component_action_lock.h"

/* DEPENDENCIES: Physics, Return */

static void _select_check(ComponentActionLock* self, ECS* ecs);
static void _redirect_arrow_set(ComponentActionLock* self, ECS* ecs);

/* Adds a redirect arrow to help with redirecting. */
static void
_redirect_arrow_set(ComponentActionLock* self, ECS* ecs)
{
	ComponentSprite* redirectArrowSprite;

	/* Check to make sure if it exists. If it doesn't, make one. */
	if (self->isRedirectArrowInit)
	{
		ComponentActionFollow* actionFollow;

		actionFollow = ecs_component_get(ecs, ECS_COMPONENT_ACTION_FOLLOW, self->redirectArrowID);

		if (!actionFollow)
			self->isRedirectArrowInit = false;
	}
	
	if (!self->isRedirectArrowInit)
	{
		ComponentSprite* sprite;
		ComponentActionPointToMouse* actionPointToMouse;

		sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->component.id);
		
		self->redirectArrowID = ecs_entity_add(ecs);

		entity_redirect_arrow_init
		(
			ecs,
			self->redirectArrowID,
			sprite->position,
			self->component.id
		);

		actionPointToMouse = ecs_component_get(ecs, ECS_COMPONENT_ACTION_POINT_TO_MOUSE, self->redirectArrowID);

		actionPointToMouse->component.isDisabled = true;

		self->isRedirectArrowInit = true;
	}

	redirectArrowSprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->redirectArrowID);

	redirectArrowSprite->rotation = self->angle;

	sound_play(&ecs->game->resources.sounds[SOUND_SELECT], SOUND_NO_PRIORITY);
}

/* Checks if the mouse has graced a radius around the locked projectile. */
/* If the mouse is moved out of it, a redirect angle is set. */
static void
_select_check(ComponentActionLock* self, ECS* ecs)
{
	Circle circle;
	vec2 mousePosition;
	ComponentPhysics* physics;
	ComponentRedirects* redirects;

	physics = ecs_component_get(ecs, ECS_COMPONENT_PHYSICS, self->component.id);
	redirects = ecs_component_get(ecs, ECS_COMPONENT_REDIRECTS, self->sender);

	circle.position[0] = physics->position[0];
	circle.position[1] = physics->position[1];

	circle.radius = self->selectRadius;

	mouse_world_position_get(&ecs->game->input.mouse, &ecs->game->renderer, mousePosition);

	if (redirects && !redirects->isOut)
	{
		if (self->isSelected)
		{
			if (!circle_has_point(&circle, mousePosition))
			{
				if (!self->isRedirectAngleGiven)
				{
					self->angle = ATAN
					(
						mousePosition[0],
						circle.position[0],
						mousePosition[1],
						circle.position[1]

					);

					_redirect_arrow_set(self, ecs);

					self->isRedirectAngleGiven = true;
				}

				self->isSelected = false;
			}
		
		}
		else
		{
			if (circle_has_point(&circle, mousePosition))
			{
				if (self->isRedirectAngleGiven)
					self->isRedirectAngleGiven = false;
				self->isSelected = true;
			}
		}
	}
}

/* Lock in place. */
void
component_action_lock_lock(ComponentActionLock* self, ECS* ecs)
{
	ComponentPhysics* physics;
	ComponentActionReturn* actionReturn;
	ComponentActionDamage* actionDamage;
	ComponentActionDeleteOnTouchEntity* actionDeleteOnTouchEntity;

	physics = ecs_component_get(ecs, ECS_COMPONENT_PHYSICS, self->component.id);
	actionReturn = ecs_component_get(ecs, ECS_COMPONENT_ACTION_RETURN, self->component.id);
	actionDamage = ecs_component_get(ecs, ECS_COMPONENT_ACTION_DAMAGE, self->component.id);
	actionDeleteOnTouchEntity = ecs_component_get(ecs, ECS_COMPONENT_ACTION_DELETE_ON_TOUCH_ENTITY, self->component.id);
	
	glm_vec3_copy(physics->velocity, self->velocity);

	actionReturn->component.isDisabled = true;
	actionDeleteOnTouchEntity->component.isDisabled = false;
	actionDamage->component.isDisabled = true;

	self->cooldown = self->cooldownMax;

	self->isLocked = true;

	sound_play(&ecs->game->resources.sounds[SOUND_LOCK], SOUND_NO_PRIORITY);
}

/* Unlocks, from being locked. */
void
component_action_lock_unlock(ComponentActionLock* self, ECS* ecs)
{
	ComponentPhysics* physics;
	ComponentActionReturn* actionReturn;
	ComponentActionDamage* actionDamage;
	ComponentActionDeleteOnTouchEntity* actionDeleteOnTouchEntity;

	physics = ecs_component_get(ecs, ECS_COMPONENT_PHYSICS, self->component.id);
	actionReturn = ecs_component_get(ecs, ECS_COMPONENT_ACTION_RETURN, self->component.id);
	actionDamage = ecs_component_get(ecs, ECS_COMPONENT_ACTION_DAMAGE, self->component.id);
	actionDeleteOnTouchEntity = ecs_component_get(ecs, ECS_COMPONENT_ACTION_DELETE_ON_TOUCH_ENTITY, self->component.id);

	glm_vec3_copy(self->velocity, physics->velocity); 
	actionReturn->component.isDisabled = false;
	actionDamage->component.isDisabled = false;

	actionDeleteOnTouchEntity->component.isDisabled = true;
	
	self->isSelected = false;
	self->isRedirectAngleGiven = false;
	self->isLocked = false;

	sound_play(&ecs->game->resources.sounds[SOUND_UNLOCK], SOUND_NO_PRIORITY);

	if (self->isRedirectArrowInit)
		ecs_entity_delete(ecs, self->redirectArrowID);
}

/* Initialize lock component. */
void
component_action_lock_init(ComponentActionLock* self, u32 cooldown, f32 selectRadius, u32 sender)
{
	self->cooldownMax = cooldown;
	self->cooldown = self->cooldownMax;
	self->selectRadius = selectRadius;
	self->sender = sender;
}

/* Ticks lock component. */
/* Remain stationary. */
void 
component_action_lock_tick(ComponentActionLock* self, ECS* ecs)
{
	ComponentPhysics* physics;

	physics = ecs_component_get(ecs, ECS_COMPONENT_PHYSICS, self->component.id);

	if (self->isLock)
	{
		if (!self->isLocked)
			component_action_lock_lock(self, ecs);

		glm_vec3_zero(physics->velocity);

		_select_check(self, ecs);

		self->cooldown--;

		if (self->cooldown <= 0)
		{
			self->cooldown = 0;
			self->isLock = false;
			component_action_lock_unlock(self, ecs);
		}
	}
	else
	{
		if (self->isLocked)
			component_action_lock_unlock(self, ecs);
	}
}
