/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.

This file is part of Quake III Arena source code.

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

Quake III Arena source code 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 bteral Public License for more details.

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



#ifndef BSP_LOADER_H
#define BSP_LOADER_H

#include "LinearMath/btAlignedObjectArray.h"

#define	BSPMAXTOKEN	1024
#define	BSPMAX_KEY				32
#define	BSPMAX_VALUE			1024
#define	BSPCONTENTS_SOLID			1
#define	BSPCONTENTS_AREAPORTAL		0x8000
#define	BSPLUMP_ENTITIES		0
#define	BSPLUMP_SHADERS		1
#define	BSPLUMP_PLANES			2
#define	BSPLUMP_NODES			3
#define	BSPLUMP_LEAFS			4
#define	BSPLUMP_LEAFSURFACES	5
#define	BSPLUMP_LEAFBRUSHES	6
#define	LUMP_MODELS			7
#define	LUMP_BRUSHES		8
#define	LUMP_BRUSHSIDES		9
#define	LUMP_DRAWVERTS		10
#define	LUMP_DRAWINDEXES	11
#define	LUMP_SURFACES		13
#define	LUMP_LIGHTMAPS		14
#define	LUMP_LIGHTGRID		15
#define	LUMP_VISIBILITY		16
#define	HEADER_LUMPS		17
#define	MAX_QPATH		64



typedef struct {
	int		fileofs, filelen;
} BSPLump;

typedef float BSPVector3[3];

typedef struct {
	int			ident;
	int			version;
	
	BSPLump		lumps[HEADER_LUMPS];
} BSPHeader;


typedef struct {
	float		mins[3], maxs[3];
	int			firstSurface, numSurfaces;
	int			firstBrush, numBrushes;
} BSPModel;

typedef struct {
	char		shader[MAX_QPATH];
	int			surfaceFlags;
	int			contentFlags;
} BSPShader;

typedef struct {
	float		normal[3];
	float		dist;
} BSPPlane;

typedef struct {
	int			planeNum;
	int			children[2];
	int			mins[3];
	int			maxs[3];
} BSPNode;

typedef struct {
	int			cluster;	
	int			area;
	
	int			mins[3];	
	int			maxs[3];
	
	int			firstLeafSurface;
	int			numLeafSurfaces;
	
	int			firstLeafBrush;
	int			numLeafBrushes;
} BSPLeaf;

typedef struct {
	int			planeNum;	
	int			shaderNum;
} BSPBrushSide;

typedef struct {
	int			firstSide;
	int			numSides;
	int			shaderNum;	
} BSPBrush;




typedef struct BSPPair {
	struct BSPPair	*next;
	char	*key;
	char	*value;
} BSPKeyValuePair;

typedef struct {
	BSPVector3		origin;
	struct bspbrush_s	*brushes;
	struct parseMesh_s	*patches;
	int			firstDrawSurf;
	BSPKeyValuePair		*epairs;
} BSPEntity;

typedef enum {
	MST_BAD,
		MST_PLANAR,
		MST_PATCH,
		MST_TRIANGLE_SOUP,
		MST_FLARE
} BSPMapSurface;

typedef struct {
	int			shaderNum;
	int			fogNum;
	int			surfaceType;
	
	int			firstVert;
	int			numVerts;
	
	int			firstIndex;
	int			numIndexes;
	
	int			lightmapNum;
	int			lightmapX, lightmapY;
	int			lightmapWidth, lightmapHeight;
	
	BSPVector3		lightmapOrigin;
	BSPVector3		lightmapVecs[3];
	
	int			patchWidth;
	int			patchHeight;
} BSPSurface;



///GPL code from IdSofware to parse a Quake 3 BSP file
///check that your platform define __BIG_ENDIAN__ correctly (in BspLoader.cpp)
class BspLoader
{
	int m_Endianness;

	public:

		BspLoader();

		bool	loadBSPFile( void* memoryBuffer);

		const char* getValueForKey( const BSPEntity *ent, const char *key ) const;

		bool	getVectorForKey( const BSPEntity *ent, const char *key, BSPVector3 vec );
		
		float	getFloatForKey( const BSPEntity *ent, const char *key );

		void parseEntities( void );

		bool findVectorByName(float* outvec,const char* name);

		const BSPEntity * getEntityByValue( const char* name, const char* value);


	protected:

		void parseFromMemory (char *buffer, int size);
		


		bool isEndOfScript (bool crossline);

		bool getToken (bool crossline);

		char *copystring(const char *s);
	
		void stripTrailing( char *e );

		BSPKeyValuePair * parseEpair( void );

		bool	parseEntity( void );

		short   isLittleShort (short l);
		int    isLittleLong (int l);
		float	isLittleFloat (float l);

		int    isBigLong (int l);
		short   isBigShort (short l);
		float	isBigFloat (float l);

		void swapBlock( int *block, int sizeOfBlock );

		int copyLump( BSPHeader	*header, int lump, void *dest, int size );

		void swapBSPFile( void );
		
	

	
	public: //easier for conversion
		int			m_num_entities;
		btAlignedObjectArray<BSPEntity>	m_entities;
		
		int			m_nummodels;
		btAlignedObjectArray<BSPModel>	m_dmodels;

		int			m_numShaders;
		btAlignedObjectArray<BSPShader>	m_dshaders;

		int			m_entdatasize;
		btAlignedObjectArray<char>		m_dentdata;

		int			m_numleafs;
		btAlignedObjectArray<BSPLeaf>		m_dleafs;

		int			m_numplanes;
		btAlignedObjectArray<BSPPlane>	m_dplanes;

		int			m_numnodes;
		btAlignedObjectArray<BSPNode>		m_dnodes;

		int			m_numleafsurfaces;
		btAlignedObjectArray<int>			m_dleafsurfaces;

		int			m_numleafbrushes;
		btAlignedObjectArray<int>			m_dleafbrushes;

		int			m_numbrushes;
		btAlignedObjectArray<BSPBrush>	m_dbrushes;

		int			m_numbrushsides;
		btAlignedObjectArray<BSPBrushSide>	m_dbrushsides;

		int			m_numLightBytes;
		btAlignedObjectArray<unsigned char>		m_lightBytes;

		int			m_numGridPoints;
		btAlignedObjectArray<unsigned char>		m_gridData;

		int			m_numVisBytes;
		btAlignedObjectArray<unsigned char>		m_visBytes;

		
		int			m_numDrawIndexes;
		btAlignedObjectArray<int>			m_drawIndexes;

		int			m_numDrawSurfaces;
		btAlignedObjectArray<BSPSurface>	m_drawSurfaces;

		enum
		{
			BSP_LITTLE_ENDIAN  = 0,
			BSP_BIG_ENDIAN    =  1,
		};

		//returns machines big endian / little endian
		//
		int getMachineEndianness();

		inline int	machineEndianness()
		{
			return m_Endianness;
		}

};

#endif //BSP_LOADER_H
