// **********************************************************************
//                            OpenAlchemist
//                        ---------------------
//
//  File        : SDL_CL_Sprite.h
//  Description : 
//  Author      : Dennis Payne <dulsi@identicalsoftware.com>
//  License     : GNU General Public License 2 or higher
//
// **********************************************************************

#ifndef _SDL_CL_SPRITE_H_
#define _SDL_CL_SPRITE_H_

#include <SDL.h>
#include <list>
#include <vector>
#include <memory>
#include <string>
#include <zip.h>

#define CL_Image SDL_CL_Image
#define CL_Sprite SDL_CL_Sprite
#define CL_Font SDL_CL_Font
#define CL_Font_Sprite SDL_CL_Font

class SDL_CL_ResourceManager;

class SDL_CL_Image_Impl
{
public:
	SDL_CL_Image_Impl();
	SDL_CL_Image_Impl(const std::string &filename, int x = -1, int y = -1, int w = -1, int h = -1);
	
	~SDL_CL_Image_Impl();

	void load(SDL_Renderer *r, zip_t *zip_file);

	std::string _filename;
	SDL_Texture *_t;
	bool _release;
	int _x,_y;
	int _h,_w;
};

class SDL_CL_Image
{
public:
	/** Constructor	*/
	SDL_CL_Image();
	SDL_CL_Image(SDL_Renderer *r, const std::string &name, SDL_CL_ResourceManager *rm);
	SDL_CL_Image(SDL_Renderer *r, const std::string &filename);

	/** Draw	*/
	void draw(SDL_Renderer *gc, int x, int y);

	int get_height();

	int get_width();

	bool is_null() { return _impl.get() == NULL; }

	void set_alpha(float a);

protected:
	std::shared_ptr<SDL_CL_Image_Impl> _impl;
};

class SDL_CL_Sprite_Impl
{
public:
	SDL_CL_Sprite_Impl() : _animation_speed(0), _start_time(-1), _cur_frame(0), _loop(true) {}

	void add_frame(const std::string &filename, int x = -1, int y = -1, int w = -1, int h = -1);
	
	void load_frames(SDL_Renderer *r, zip_t *zip_file);

	/** Animation speed */
	int _animation_speed;

	int _cur_frame;
	int _start_time;
	bool _loop;

	std::vector<std::shared_ptr<SDL_CL_Image_Impl> > frame;
};

class SDL_CL_Sprite
{
public:
	/** Constructor	*/
	SDL_CL_Sprite();
	SDL_CL_Sprite(SDL_Renderer *r, const std::string &name, SDL_CL_ResourceManager *rm);

	/** Destructor */
	~SDL_CL_Sprite();

	/** Draw	*/
	void draw(SDL_Renderer *gc, int x, int y);

	int get_height();

	int get_width();

	bool is_finished();

	void restart();

	void set_alpha(float a);

	void set_play_loop(bool loop);

	/** Update */
	void update();  

protected:
	std::shared_ptr<SDL_CL_Sprite_Impl> _impl;
};

class SDL_CL_Font_Impl
{
public:
	class SDL_ColoredFont
	{
	public:
		SDL_ColoredFont(SDL_Color c, SDL_Texture *t) : _c(c), _t(t) {}
		~SDL_ColoredFont() { SDL_DestroyTexture(_t); }

		SDL_Color _c;
		SDL_Texture *_t;
	};

	SDL_Texture *get_colored_font(SDL_Renderer *gc, SDL_Color c);

	std::string _letters;
	int _spacelen;
	std::string _glyphs;
	std::shared_ptr<SDL_CL_Sprite_Impl> _sprite;
	std::list<std::unique_ptr<SDL_ColoredFont> > _color_texture;
};

class SDL_CL_Font
{
public:
	SDL_CL_Font();
	SDL_CL_Font(SDL_Renderer *r, const std::string &name, SDL_CL_ResourceManager *rm);

	void draw_text(SDL_Renderer *r, int x, int y, const std::string &text);
	void draw_text(SDL_Renderer *r, int x, int y, const std::string &text, SDL_Color c);
	int get_text_width(SDL_Renderer *r, const std::string &text);
	int get_text_height(SDL_Renderer *r, const std::string &text);

protected:
	std::shared_ptr<SDL_CL_Font_Impl> _impl;
};

#endif
