#include "component_hud_display.h"

/* DEPENDENCIES: Text, Sprite */

static void _string_get(ComponentHUDDisplay* self, ECS* ecs, char* string);
static void _string_set(ComponentHUDDisplay* self, ECS* ecs);
static bool _stat_compare(ComponentHUDDisplay* self, ECS* ecs);

/* Obtains the string used for the HUD display. */
static void
_string_get(ComponentHUDDisplay* self, ECS* ecs, char* string)
{
	HUDDisplayStat* stat;
	u32 milliseconds;
	u32 seconds;
	u32 minutes;
	u32 value;

	stat = (HUDDisplayStat*)ecs_component_get(ecs, self->type, self->id);

	value = (f32)stat->value;

	minutes = (u32)((f32)value / MINUTE_TICK);
	seconds = (u32)((f32)value / SECOND_TICK) % SECOND_TICK;
	milliseconds = (((f32)value - ((minutes * MINUTE_TICK) + (seconds * SECOND_TICK))) / SECOND_TICK) * 100;

	switch (self->formatType)
	{
		case HUD_DISPLAY_FORMAT_WAVE:
			snprintf
			(
				string,
				COMPONENT_HUD_DISPLAY_TEXT_MAX,
				COMPONENT_HUD_DISPLAY_TEXT_FORMAT_WAVE,
				value
			);
			break;
		case HUD_DISPLAY_FORMAT_MULTIPLIER:
			snprintf
			(
				string,
				COMPONENT_HUD_DISPLAY_TEXT_MAX,
				COMPONENT_HUD_DISPLAY_TEXT_FORMAT_MULTIPLIER,
				value
			);
			break;
		case HUD_DISPLAY_FORMAT_TIME_MM_SS:
			snprintf
			(
				string,
				COMPONENT_HUD_DISPLAY_TEXT_MAX,
				COMPONENT_HUD_DISPLAY_TEXT_FORMAT_TIME_MM_SS,
				(u32)minutes,
				(u32)seconds
			);
			break;
		case HUD_DISPLAY_FORMAT_TIME_MM_SS_MS:
			snprintf
			(
				string,
				COMPONENT_HUD_DISPLAY_TEXT_MAX,
				COMPONENT_HUD_DISPLAY_TEXT_FORMAT_TIME_MM_SS_MS,
				(u32)minutes,
				(u32)seconds,
				(u32)milliseconds
			);
			break;
		case HUD_DISPLAY_FORMAT_VALUE:
		default:
			snprintf
			(
				string,
				COMPONENT_HUD_DISPLAY_TEXT_MAX,
				COMPONENT_HUD_DISPLAY_TEXT_FORMAT_VALUE,
				value
			);
			break;
	}
}

/* Sets string used for the HUD display. */
static void
_string_set(ComponentHUDDisplay* self, ECS* ecs)
{
	ComponentText* text;
	char string[COMPONENT_HUD_DISPLAY_TEXT_MAX];

	text = ecs_component_get(ecs, ECS_COMPONENT_TEXT, self->component.id);

	_string_get(self, ecs, string);

	component_text_string_set
	(
		text,
		string,
		strlen(string)
	);

}

/* Compares the present and prior stats. */
static bool
_stat_compare(ComponentHUDDisplay* self, ECS* ecs)
{
	HUDDisplayStat* stat;

	stat = (HUDDisplayStat*)ecs_component_get(ecs, self->type, self->id);

	if (stat->value == self->oldValue)
		return true;

	return false;
}

/* Initializes a hud_display component. */
void component_hud_display_init
(
	ComponentHUDDisplay* self, 
	ECS* ecs,
	vec3 position,
	u32 id,
	HUDDisplayFormatType formatType,
	IconType iconType,
	ECSComponentType type
)
{
	ComponentText* text;
	Rectangle rectangle;
	char string[COMPONENT_HUD_DISPLAY_TEXT_MAX];
	vec2 size;
	vec3 iconPosition;
	vec3 textPosition;

	glm_vec2_copy((f32*)COMPONENT_HUD_DISPLAY_STREAK_SIZE, size);

	text = ecs_component_get(ecs, ECS_COMPONENT_TEXT, self->component.id);

	self->streakID = ecs_entity_add(ecs);
	self->iconID = ecs_entity_add(ecs);
	
	self->formatType = formatType;
	self->type = type;
	self->id = id;

	_string_get(self, ecs, string);

	entity_streak_init
	(
		ecs,
		self->streakID,
		position,
		size
	);

	glm_vec3_copy(position, textPosition);

	component_text_init
	(
		text,
		&ecs->game->resources.fonts[FONT_HUD],
		string,
		strlen(string),
		-1,
		position,
		(f32*)COMPONENT_HUD_DISPLAY_TEXT_COLOR
	);

	component_text_rectangle_get(text, &rectangle);

	text->position[0] -= (rectangle.w / 2);
	text->position[0] += COMPONENT_HUD_DISPLAY_TEXT_X_OFFSET;
	text->position[1] -= rectangle.h;
	text->position[1] += COMPONENT_HUD_DISPLAY_TEXT_Y_OFFSET;
	text->position[2] += COMPONENT_HUD_DISPLAY_TEXT_Z_OFFSET;

	glm_vec3_copy(position, iconPosition);

	iconPosition[0] += COMPONENT_HUD_DISPLAY_ICON_X_OFFSET;
	iconPosition[2] += COMPONENT_HUD_DISPLAY_ICON_Z_OFFSET;

	entity_icon_init
	(
		ecs,
		self->iconID,
		iconPosition,
		(f32*)COMPONENT_HUD_DISPLAY_ICON_SIZE,
		iconType
	);
}

/* Runs on adding a stat display component. */
void
component_hud_display_add(ComponentHUDDisplay* self, ECS* ecs)
{
	ecs_component_add(ecs, ECS_COMPONENT_TEXT, self->component.id);
}

/* Runs on adding a stat display component. */
void
component_hud_display_delete(ComponentHUDDisplay* self, ECS* ecs)
{
	ecs_component_delete(ecs, ECS_COMPONENT_TEXT, self->component.id);
	ecs_component_delete(ecs, ECS_COMPONENT_SPRITE, self->streakID);
}

/* Ticks hud_display component. */
void 
component_hud_display_tick(ComponentHUDDisplay* self, ECS* ecs)
{
	HUDDisplayStat* stat;

	stat = (HUDDisplayStat*)ecs_component_get(ecs, self->type, self->id);

	if (!_stat_compare(self, ecs))
		_string_set(self, ecs);

	self->oldValue = stat->value;
}
