#ifndef _H_ANIMATION_H
#define _H_ANIMATION_H

#include <memory>
#include <SDL_timer.h>
#include <vector>
#include <string>
#include <unordered_map>

#include "utility/xmlloader.h"
#include "utility/direction.h"
#include "graphics/sprite.h"

class ResourceManager;
class EventManager;

// Each entity will contain animation data,
// this data will hold:
// name of the animation,
// type of animation ie. idle animation, directional, etc.
// directory of the animation atlas containing the frames

struct Animation {
	const AnimationData *data;
	SpriteAtlas *spriteAtlas;

	bool playing;

	float FPS;
	unsigned int elapsedTime = 0;
	unsigned int lastFrameTick = 0;
	unsigned int currentFrame;
	int cycles;

	Direction facingDir;

	void reset() {
		elapsedTime = 0;
		lastFrameTick = 0;
		currentFrame = 0;
	};

	void bind() {
		spriteAtlas->bind();
	}

	void tick() {
		Uint32 currentTime = SDL_GetTicks();
		elapsedTime = currentTime - lastFrameTick;
		if (elapsedTime >= 1000.0f / FPS) {
			if (++currentFrame > spriteAtlas->size() - 1) {
				currentFrame = 0;
				cycles += 1;
			}
			lastFrameTick = currentTime;
		}
	}

	void draw() {
		if (playing) {
			tick();
		} else if (!data->directional) {
			currentFrame = 0;
		}
		auto frame = (data->directional) ? 
			spriteAtlas->frame(currentFrame, facingDir) : 
			spriteAtlas->frame(currentFrame);

		spriteAtlas->bindFrame(&frame);
		spriteAtlas->draw();
	}
};

struct AnimationComponent {
	int entityID;
	//								 anim-id			animation
	std::unordered_map<std::string, std::unique_ptr<Animation>> anims;
	Animation *curAnim;
};

/*
class Animation
{
public:
	Animation(const AnimationData* animData, ResourceManager* resourceManager);

	std::string getPrefix() const { return prefix; }
	std::string getType() const { return type; }
	std::string getID() const { return prefix + "/" + type; }

	void bind();
	void draw();
	void draw(Direction dir);

	void play() { isPlaying = true; }
	void stop() { isPlaying = false; }
	void reset() { currentFrame = 0; lastFrameTick = 0; elapsedTime = 0; }

	const bool getPlaying() const		{ return isPlaying; }
	const bool getDirectional() const	{ return isDirectional; }
	const int  getCycles()	const		{ return cycles; }

	void setFPS(const float fps) { FPS = fps; }

private:
	std::string prefix;
	std::string type;

	SpriteAtlas* spriteAtlas;

	Uint32 elapsedTime = 0;
	Uint32 lastFrameTick = 0;
	float FPS;
	int currentFrame;
	int cycles;

	bool isDirectional;
	bool isPlaying;

	// this ticks our frame forward according to ticks passed
	void frameTick();

	void singleDraw();
	void directionalDraw(Direction dir);
};
*/

// We will load our animation component with every loaded animation, 
// this will be the handler for every animation an entity uses
class AnimationSystem
{
public:
	AnimationSystem(std::weak_ptr<ResourceManager> resourceManger, std::weak_ptr<EventManager> eventManager);
	// animID is the first two elements in the ID <TYPE>/<OBJ>. The prefix
	bool registerComponent(const int entityID, const std::string& animID);

	void update();
	void draw();

	~AnimationSystem();

private:

	void registerEvents(AnimationComponent *component);

	std::vector<std::unique_ptr<AnimationComponent>> animComponents;
	std::weak_ptr<EventManager> eventManager;
	std::weak_ptr<ResourceManager> resourceManager;
};

#endif // _H_ANIMATION_H
