#ifndef _H_ENTITY_H
#define _H_ENTITY_H

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <SDL_timer.h>

#include "graphics/renderer.h"
#include "util.h"

class Camera;
struct PhysicsComponent;
// TODO: Allow speed to be changed and add speed as creation value in XML File!
// TODO: Create Entity System that loads entity types and creates them in scene according to name.
class Entity : public Drawable
{
public:
	Entity(unsigned shaderID) :
		position(glm::vec3(0.0f)),
		scale(glm::vec3(1.0f)),
		rotation(0.0f),
		speed(20.0f),
		entityid(SDL_GetTicks())
	{ this->shaderID = shaderID; };
	virtual ~Entity() {};

	void setPosition(const glm::vec3& position);
	void setScale(const glm::vec3& scale);
	virtual void setRotation(const float& rotation);
	void setLocalPosition(const glm::vec3& localPosition);
	void setRotatable(bool rotatable);

	void flip();

	void addPhysicsComponent(const std::shared_ptr<PhysicsComponent>& physics);

	const glm::vec3& getPosition() const { return this->position; }
	const glm::vec3& getScale() const { return this->scale; }
	const float getRotation() const { return this->rotation; }
	const bool isFlipped() const { return flipped; }
	const glm::vec2 getFacingDir() const { return glm::vec2(cos(glm::radians(rotation)), sin(glm::radians(rotation))); }
	const glm::vec3 getCenter() const { return glm::vec3(position.x, position.y, 0.0f); }
	//const glm::vec3 getCenter() const { return glm::vec3(position.x + (0.5f * scale.x), position.y + (0.5f * scale.y), 0.0f); }
	const bool getIsMoving() const { return isMoving; }
	const int getEntityID() const { return entityid; }
	const std::shared_ptr<PhysicsComponent> getPhysicsComponent() const { return physics; }
	const unsigned getShaderID() const { return shaderID; }

	// TODO: right now there is no default behavior, but eventually the Entity class will be expanded to handle physics
	virtual void update(double deltaTime) = 0;
	virtual void draw() = 0;

protected:
	glm::vec3 localPosition;
	glm::vec3 position;
	glm::vec3 deltaPosition; // future position frame, updated in update
	glm::vec3 scale;
	float rotation;
	float speed;

	int entityid;

	// Should consider move to using unique pointers for this.
	std::shared_ptr<PhysicsComponent> physics;

	bool isMoving = false;
	bool wasMoving = false;
	bool isRotatable = true;
	bool flipped = false;

	glm::mat4 modelMatrix;

	void updateModelMatrix();
};


#endif //_H_ENTITY_H
