/*  TA3D, a remake of Total Annihilation
    Copyright (C) 2005  Roland BROCHARD

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA*/

/*-----------------------------------------------------------------------------------\
|                                         gaf.h                                      |
|  ce fichier contient les structures, classes et fonctions nécessaires à la lecture |
| des fichiers gaf de total annihilation qui sont les fichiers contenant les images  |
| et les animations du jeu.                                                          |
|                                                                                    |
\-----------------------------------------------------------------------------------*/

#ifndef __GAF_CLASSES
#define __GAF_CLASSES

struct GAFHEADER
{
	int		IDVersion;	/* Version stamp - always 0x00010100 */
	int		Entries;	/* Number of items contained in this file */
	int		Unknown1;	/* Always 0 */
};

struct GAFENTRY
{
	short	Frames;		/* Number of frames in this entry */
	short	Unknown1;	/* Unknown - always 1 */
	int		Unknown2;	/* Unknown - always 0 */
	char	Name[32];	/* Name of the entry */
};

struct GAFFRAMEENTRY
{
	int		PtrFrameTable;	/* Pointer to frame data */
	int		Unknown1;		/* Unknown - varies */
};

struct GAFFRAMEDATA
{
	short	Width;			/* Width of the frame */
	short	Height;			/* Height of the frame */
	short	XPos;			/* X offset */
	short	YPos;			/* Y offset */
	char	Unknown1;		/* Unknown - always 9 */
	char	Compressed;		/* Compression flag */
	short	FramePointers;	/* Count of subframes */
	int		Unknown2;		/* Unknown - always 0 */
	int		PtrFrameData;	/* Pointer to pixels or subframes */
	int		Unknown3;		/* Unknown - value varies */
};

int get_gaf_nb_entry(byte *buf);

char *get_gaf_entry_name(byte *buf,int entry_idx);

int get_gaf_entry_index(byte *buf,char *name);

int get_gaf_nb_img(byte *buf,int entry_idx);

BITMAP *read_gaf_img(byte *buf,int entry_idx,int img_idx,short *ofs_x=NULL,short *ofs_y=NULL,bool truecol=true);			// Lit une image d'un fichier gaf en mémoire

class ANIM			// Pour la lecture des fichiers GAF animés
{
public:
	int		nb_bmp;
	BITMAP	**bmp;
	short	*ofs_x;
	short	*ofs_y;
	short	*w,*h;
	GLuint	*glbmp;
	char	*name;

	inline void init()
	{
		nb_bmp=0;
		bmp=NULL;
		ofs_x=ofs_y=NULL;
		glbmp=NULL;
		w=h=NULL;
		name=NULL;
	}

	ANIM()
	{
		init();
	}

	inline void destroy()
	{
		if(nb_bmp>0) {
			for(int i=0;i<nb_bmp;i++) {
				if(bmp[i])
					destroy_bitmap(bmp[i]);
				glDeleteTextures(1,&(glbmp[i]));
				}
			if(w)
				free(w);
			if(h)
				free(h);
			if(name)
				free(name);
			if(ofs_x)
				free(ofs_x);
			if(ofs_y)
				free(ofs_y);
			free(bmp);
			free(glbmp);
			}
		init();
	}

	~ANIM()
	{
		destroy();
	}

	void load_gaf(byte *buf,int entry_idx=0)
	{
		nb_bmp=get_gaf_nb_img(buf,entry_idx);

		bmp=(BITMAP**) malloc(sizeof(BITMAP*)*nb_bmp);
		glbmp=(GLuint*) malloc(sizeof(GLuint)*nb_bmp);
		ofs_x=(short*) malloc(sizeof(short)*nb_bmp);
		ofs_y=(short*) malloc(sizeof(short)*nb_bmp);
		w=(short*) malloc(sizeof(short)*nb_bmp);
		h=(short*) malloc(sizeof(short)*nb_bmp);
		name=get_gaf_entry_name(buf,entry_idx);

        int i=0,f=0;
        for(;i<nb_bmp;i++) {
            if ((bmp[i-f]=read_gaf_img(buf,entry_idx,i,&(ofs_x[i-f]),&(ofs_y[i-f])))!=NULL) {
                w[i-f]=bmp[i-f]->w;
                h[i-f]=bmp[i-f]->h;
            }
            else f++;
        }
        nb_bmp -= f;
	}

	void convert(bool NO_FILTER=false,bool COMPRESSED=false)
	{
		for(int i=0;i<nb_bmp;i++) {
			BITMAP *tmp=create_bitmap(bmp[i]->w,bmp[i]->h);
			blit(bmp[i],tmp,0,0,0,0,tmp->w,tmp->h);
			destroy_bitmap(bmp[i]);
			bmp[i]=tmp;
			if(g_useTextureCompression && COMPRESSED)
				allegro_gl_set_texture_format(GL_COMPRESSED_RGBA_ARB);
			else
				allegro_gl_set_texture_format(GL_RGBA8);
			allegro_gl_use_alpha_channel(true);
			glbmp[i]=allegro_gl_make_texture(bmp[i]);
			allegro_gl_use_alpha_channel(false);
			glBindTexture(GL_TEXTURE_2D,glbmp[i]);
			if(NO_FILTER) {
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
				}
			else {
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
				}
			}
	}

	void clean()
	{
		for(int i=0;i<nb_bmp;i++) {		// Fait un peu le ménage
			if(bmp[i])
				destroy_bitmap(bmp[i]);
			bmp[i]=NULL;
			}
		if(name) {
			free(name);
			name=NULL;
			}
	}
};

class ANIMS			// Pour la lecture des fichiers GAF animés
{
public:
	int		nb_anim;
	ANIM	*anm;

	inline void init()
	{
		nb_anim=0;
		anm=NULL;
	}

	ANIMS()
	{
		init();
	}

	inline void destroy()
	{
		if(nb_anim>0) {
			for(int i=0;i<nb_anim;i++)
				anm[i].destroy();
			free(anm);
			}
		init();
	}

	~ANIMS()
	{
		destroy();
	}

	void load_gaf(byte *buf)
	{
		nb_anim=get_gaf_nb_entry(buf);

		anm=(ANIM*) malloc(sizeof(ANIM)*nb_anim);

		for(int i=0;i<nb_anim;i++)
			anm[i].load_gaf(buf,i);
	}

	void convert(bool no_filter=false,bool compressed=false)
	{
		for(int i=0;i<nb_anim;i++)
			anm[i].convert(no_filter,compressed);
	}

	void clean()
	{
		for(int i=0;i<nb_anim;i++)
			anm[i].clean();
	}

	int find_entry(char *name)
	{
		for(int i=0;i<nb_anim;i++)
			if(anm[i].name!=NULL && strcasecmp(anm[i].name,name)==0)
				return i;
		return -1;
	}
};
#endif
