/***************************************************************************
 *            utility.h
 *
 *  Sat Mar 26 08:48:31 2005
 *  Copyright  2005  Joe Venzon
 *  joe@venzon.net
 ****************************************************************************/

/*
 *  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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
//#define GL_GLEXT_PROTOTYPES
 
#ifndef _UTILITY_H

#ifdef __APPLE__ 
#include "definitions_mac.h" 
#else 
#include "definitions.h" 
#endif 

 
#include <stdio.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <SDL/SDL.h>
#ifdef __APPLE__
	#include <SDL_image/SDL_image.h>
	#include "SDL_rotozoom.h" 
#else
	#include <SDL/SDL_image.h>
	#include <SDL/SDL_rotozoom.h> //part of the SDL_gfx package
#endif

#include <math.h>
#include <string>
#include <fstream>
#include <iostream>

#include <map>
#include <list>

#include "quat.h"
#include "cardinfo.h"
#include "globals.h"

using namespace std;

#define ENDOFFILESTRING "!!!END OF FILE!!!"

#define EPSILON 0.000001
//#define EPSILON 0.00001
#define CROSS(dest,v1,v2) \
          dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
          dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
          dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
#define SUB(dest,v1,v2) \
          dest[0]=v1[0]-v2[0]; \
          dest[1]=v1[1]-v2[1]; \
          dest[2]=v1[2]-v2[2]; 
          
#ifdef ENABLE_NLS
	#include <libintl.h>
	#include <locale.h>
	#define _(string) gettext (string.c_str ())
	#define _c(string) gettext (string)
#else
	#define _(string) (string)
	#define _c(string) (string)
#endif

#define LISTITERATE(ttype,target,it) for(list <ttype>::iterator it = target.begin(); it != target.end(); it++)
#define VECTORITERATE(ttype,target,it) for(vector <ttype>::iterator it = target.begin(); it != target.end(); it++)

//#define TEST_CULL

class TEXTURE_HANDLE;

class UTILITY
{
private:
	ofstream error_log;
	GLint nb_multitexture;
	bool initdone;
	string texture_size;
	void initerror();
	
public:
	UTILITY();
	~UTILITY();
	void Init();
	GLuint TexLoad(string texfile, bool mipmap);
	GLuint TexLoad(string texfile, int format, bool mipmap);
	GLuint TexLoad(string texfile, int format, bool mipmap, bool cube, int &w, int &h, const bool supresserror, bool &err);
	GLuint TexLoad(string texfile, int format, bool mipmap, bool cube, int &w, int &h, const bool supresserror, bool &err, int attempt);
	GLuint TexLoad(string texfile, SDL_Surface* surface, int format, bool mipmap, bool cube, int &w, int &h, const bool supresserror, bool &err);
	void SelectTU(int TU);
	void Tex2D(int TU, bool enable);
	void TexCoord2d2f(int TU, float u, float v);
	string sGetLine(ifstream &ffrom);
	string sGetParam(ifstream &ffrom);
	int iGetParam(ifstream &ffrom);
	float fGetParam(ifstream &ffrom);
	bool bGetParam(ifstream &ffrom);
	int numTUs();
	void Draw2D(float x1, float y1, float x2, float y2, const TEXTURE_HANDLE * const texid);
	void Draw2D(float x1, float y1, float x2, float y2, const TEXTURE_HANDLE * const texid, float rotation);
	void Draw2D(float x1, float y1, float x2, float y2, const TEXTURE_HANDLE * const texid, float rotation, int texsize);
	void Draw2D(float x1, float y1, float x2, float y2, const TEXTURE_HANDLE * const texid, float rotation, int texsize, float opacity);
	void DrawButton(float x1, float y1, float x2, float y2, float sidewidth, TEXTURE_HANDLE * texid, float opacity);
	void DrawEllipse( float center_x, float center_y, float radius_x, float radius_y ) { DrawEllipse( center_x, center_y, radius_x, radius_y, 0.0f, 0.0f, 0.0f ); }
	void DrawEllipse( float center_x, float center_y, float radius_x, float radius_y, float color_r, float color_g, float color_b ) { DrawEllipse( center_x, center_y, radius_x, radius_y, color_r, color_g, color_b, 1.0f ); }
	void DrawEllipse( float center_x, float center_y, float radius_x, float radius_y, float color_r, float color_g, float color_b, float opacity );
	string GetEOFString() {return ENDOFFILESTRING;}
	float GetValue(SDL_Surface * surf, int channel, float x, float y, bool interpolate);
	float GetValue(SDL_Surface * surf, int channel, float x, float y, bool interpolate, bool wrap);
	bool FileExists(string filename);
	int IntersectTriangleD(double orig[3], double dir[3],
                   double vert0[3], double vert1[3], double vert2[3],
                   double *t, double *u, double *v);
	int IntersectTriangleF(float orig[3], float dir[3],
                   float vert0[3], float vert1[3], float vert2[3],
                   float *t, float *u, float *v);
	bool IntersectQuadrilateralF(VERTEX orig, VERTEX dir,
					VERTEX v_00, VERTEX v_10, VERTEX v_11, VERTEX v_01,
					float &t, float &u, float &v);
	bool IntersectQuadrilateralD(VERTEXD orig, VERTEXD dir,
					VERTEXD v_00, VERTEXD v_10, VERTEXD v_11, VERTEXD v_01,
					double &t, double &u, double &v);
	int BruteForceTriangleIntersectionF(VERTEX * tri1, VERTEX * tri2, 
					VERTEX & colpt, VERTEX & colseg, VERTEX & coldest, int & whichtri);
	int BruteForceTriangleIntersectionF2(VERTEX * tri1, VERTEX * tri2, 
					VERTEX & colpt, VERTEX & colseg, VERTEX & coldest, int & whichtri,
					float & destdepth, float & origdepth);
	int MollerTriTriIsectWithLine(float * V0, float * V1, float * V2,
					float * U0, float * U1, float * U2, int * coplanar,
					float * isectpt1, float * isectpt2);
	bool FileCopy(const string& srcfile, const string& dstfile) const;
	string GetPathFromFilename(string filename);
	bool isNaN(float val);
	bool DirExists(string folderpath);
	bool GetFolderIndex(string folderpath, list <string> & outputfolderlist);
	double dabs(double val);
};

#define _UTILITY_H
#endif /* _UTILITY_H */
