#include "generale.h"
#include "assets.h"
#include "game.h"

void initGenerale(Entity * entity, Game * game) {
	entity->model = &game->assets.models[GENERALE_ASSET];
	entity->collisionModel = entityCreateCollisionModel(*entity->model);
	entity->transformedCollisionModel = entityCreateCollisionModel(*entity->model);
	setEntityRadius(entity);

	// Allocate data.
	entity->data = KF_MALLOC(sizeof(Generale));

	if (entity->data == NULL) {
		ALLOCATION_ERROR;
		return;
	}

	Generale * data = (Generale*)entity->data;

	data->flyToPoint = (EntityFlyToPointInfo){
		.controller.bangbang.speed = 100.0,
		.controller.bangbang.stopAt = 0.0,
		.controlType = ENTITY_FLY_TO_POINT_BANG_BANG,
		.rotationSpeed = 0.0,
		.applyRotation = false
	};

	data->zigzag = GENERALE_ZIG;
	data->targetNotSet = true;
}

void closeGenerale(Entity * entity) {
	if (entity->data != NULL)
		KF_FREE(entity->data);

	entityFreeCollisionModel(entity->collisionModel);
	entityFreeCollisionModel(entity->transformedCollisionModel);
}

void updateGenerale(Game * game, Entity * entity) {
	entityUpdateLastValues(entity);

	Generale * data = (Generale*)entity->data;

	// Next point.
	if (data->targetNotSet) {
		getTargetGenerale(game, entity);
		data->targetNotSet = false;
	} else if (Vector3Distance(entity->position, data->target) <= GENERALE_NEXT_POINT_THRESHOLD )
		getTargetGenerale(game, entity);

	entityFlyToPoint(
		entity,
		data->target,
		&data->flyToPoint
	);

	entityCheckTransformedCollisionModel(entity);
}

void drawGenerale(Game * game, Entity * entity) {
	entityDraw(entity);

	//Generale * data = (Generale*)entity->data;

	//DrawLine3D(
	//	entity->position,
	//	data->target,
	//	BLUE
	//);

	//DrawCubeV(data->target, Vector3One(), BLUE);
}

void getTargetGenerale(Game * game, Entity * entity) {
	Entity * player = getEntityFromWorld(game->world, 0);
	Generale * data = (Generale*)entity->data;

	Vector3 dis = Vector3Subtract(player->position, entity->position);
	Vector3 dir = Vector3Normalize(dis);

	SetRandomSeed(time(NULL));
	float targetDis = GetRandomValue(GENERALE_ZIGZAG_SIZE_MIN, GENERALE_ZIGZAG_SIZE_MAX);
	float distance = Vector3Distance(entity->position, player->position);

	if (distance < targetDis)
		targetDis = distance;

	if (data->zigzag == GENERALE_ZIG) {
		dir = Vector3RotateByAxisAngle(dir, Vector3One(), PI/4);
		data->zigzag = GENERALE_ZAG;
	} else {
		dir = Vector3RotateByAxisAngle(dir, Vector3One(), -PI/4);
		data->zigzag = GENERALE_ZIG;
	}

	dir = Vector3Scale(dir, targetDis);
	data->target = Vector3Add(entity->position, dir);
}