////////////////////////////////////////////////////////////////////////////////
// Class TextureCompiler
// Copyright Björn Ganster
// Developed since 2005
// This file declares a class for compiling several smaller textures into an
// atlas. While it cannot guarantee that the resulting texture fits into 
// the limits imposed by GL_MAX_TEXTURE_SIZE, it does its best to keep the
// resulting texture as small as possible.
////////////////////////////////////////////////////////////////////////////////

#ifndef TextureCompiler__h
#define TextureCompiler__h

////////////////////////////////////////////////////////////////////////////////
// Includes

#include "Texture.h"

#include <vector>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
// Managed Texture (help class of TextureCompiler)

class ManagedTexture: public VirtualClass {
public:
	Texture* texture;
	double u1, v1, u2, v2;
	int ID, xreps, yreps;

	// Constructor
	ManagedTexture();

	// Destructor
	~ManagedTexture() OVERRIDE;

	// Transform coordinates local to texture into global coordinates
	double transformU (double u) const;
	double transformV (double v) const;

	inline int getID () const
	{ return ID; }

	inline void setID (int newVal)
	{ ID = newVal; }

	void checkUVs (int u, int v)
	{
		if (texture->getWidth() <= 0 || texture->getHeight() <= 0) {
			return;
		}
		if (u > 0) {
			int newXreps = (u+((int) texture->getWidth())-1) / ((int) texture->getWidth());
			if (newXreps > xreps)
				xreps = newXreps;
			//xreps = 1; // ???
		}
		if (v > 0) {
			int newYreps = (v+((int) texture->getHeight())-1) / ((int) texture->getHeight());
			if (newYreps > yreps)
				yreps = newYreps;
			//yreps = 1; // ???
		}
	}

   inline int getXreps() const
   { return xreps; }
   inline int getYreps() const
   { return yreps; }
private:
};

////////////////////////////////////////////////////////////////////////////////
// Texture compiler compiles several managed textures into an 

class TextureCompiler: public VirtualClass {
public:
	// Constructor
	TextureCompiler();

	// Destructor
	~TextureCompiler() OVERRIDE;

	// Add texture to list of managed textures
	ManagedTexture* add(Texture* texture, int ID = 0);

	// Build OpenGL texture from list of textures, user should free its memory
	Texture* buildAtlas();

	// Get width/height
	size_t GetWidth();
	size_t GetHeight();

	// Find named texture
	//ManagedTexture* findNamedTexture(const char* name) const;
	ManagedTexture* findTextureByID(int ID) const;

	// Get texture
	ManagedTexture* getTexture(size_t i);

	// Get number of included textures
	size_t getTextureCount() const;

	// Get atlas
	Texture* getAtlas();

	// Manage textures by ID
	bool removeAndDeleteTextureByID(int ID);
	ManagedTexture* getTextureByID(int ID);

	// Reassign UV mappings in all managed textures
	bool reassignPatches();

	void clearAtlas();

	void flipCopy(const Texture* source, TextureDim su1, TextureDim sv1, TextureDim su2, TextureDim sv2, 
		Texture* target, TextureDim tu, TextureDim tv, bool flipX, bool flipY);
private:
	Texture* atlas;
	vector<ManagedTexture*> textures;
	size_t usedWidth, usedHeight;
};

#endif
