#include "gameplay/entity.h"
#include "gameplay/physics.h"

void Entity::setPosition(const glm::vec3& position)
{
	this->position = position;
	updateModelMatrix();
}
void Entity::setScale(const glm::vec3& scale)
{
	this->scale = scale;
	updateModelMatrix();
}
void Entity::setRotation(const float& rotation)
{
	this->rotation = rotation;
	updateModelMatrix();
}

void Entity::setLocalPosition(const glm::vec3& localPosition)
{
	this->localPosition = localPosition;
}

void Entity::setRotatable(bool rotatable)
{
	this->isRotatable = rotatable;
}

void Entity::flip()
{
	flipped = !flipped;
}

// Add physics component implies more than one can be attached to an entity...
void Entity::addPhysicsComponent(const std::shared_ptr<PhysicsComponent>& physics)
{
	this->physics = physics;
}

void Entity::update(double deltaTime)
{
  // If our entity has a physics component attached and that they're moving, 
  // we will update the entity position to match the rigidBody position.
	if (physics && physics->rigidBody.velocity != glm::vec2(0.0f))
	{
		position = glm::vec3(physics->rigidBody.position, 0.f);
		updateModelMatrix();
		deltaPosition = glm::vec3(0.0f);
	}
	else if (!physics)
	{
    // In the case that the entity does not have a physics component we will handle movement on the entity itself.
		position += deltaPosition * 1.f;
		updateModelMatrix();
		deltaPosition = glm::vec3(0.f);
	}
}

// The entity will only need to update its model matrix and the flipped flag on its attached shader. 
// The shader and sprite component will handle the drawing.
void Entity::draw()
{
	editUniform("model", modelMatrix);
	editUniform("flip", flipped);
}

void Entity::updateModelMatrix()
{
  // Quick sanity check to make sure our Z position is zero. Since we are in 2D
	position.z = 0.f;
	glm::mat4 rotationMat = (isRotatable) ? glm::rotate(glm::mat4(1.f), glm::radians(rotation), glm::vec3(0.0f, 0.0f, 1.0f)) : glm::mat4(1.0f);
	glm::mat4 translation = glm::translate(glm::mat4(1.f), position);
	modelMatrix =
		translation *
		rotationMat *
		glm::scale(glm::mat4(1.0f), scale);
}
