#include "CALreader.h"
#include "./console/StrException.h"

namespace calSpace
{

void toUpperCase(string &str)
{
	std::transform(str.begin(), str.end(), str.begin() , ::toupper);
}
CALReader::CALReader(const string &fileName)
{
	this->file.open(fileName.c_str() );

	if ( this->file.fail() )
	{
		throw StrException( "Could not open CAL file `%s' for reading.", fileName.c_str() );
	}

	this->dstCamera = NULL;
	this->dstLight = NULL;
	this->dstMaterial = NULL;
	this->dstModel = NULL;
	this->dstSkybox = NULL;
	this->dstTexture = NULL;
	this->dstTerrain = NULL;
	this->dstGraphicGeneratorContainer = NULL;
}
void CALReader::setCameraContainer( CameraContainer &dstCamera )
{
	this->dstCamera = &dstCamera;
}
void CALReader::setLightContainer( LightContainer &dstLight )
{
	this->dstLight = &dstLight;
}
void CALReader::setMaterialContainer( MaterialContainer &dstMaterial )
{
	this->dstMaterial = &dstMaterial;
}
void CALReader::setModelContainer( ModelContainer &dstModel )
{
	this->dstModel = &dstModel;
}
void CALReader::setTextureContainer( TextureContainer &dstTexture )
{
	this->dstTexture = &dstTexture;
}
void CALReader::setSkyboxContainer( SkyboxContainer &dstSkybox )
{
	this->dstSkybox = &dstSkybox;
}
void CALReader::setTerrainContainer( TerrainContainer &dstTerrain )
{
	this->dstTerrain = &dstTerrain;
}
void CALReader::setGraphicGeneratorContainer( GraphicGeneratorContainer &dstGraphicGeneratorContainer )
{
	this->dstGraphicGeneratorContainer = &dstGraphicGeneratorContainer;
}
void CALReader::parseCamera( fstream &file, CameraCAL &dstCam )
{
	bool posOk=false;
	bool dirOk=false;
	bool rightOk=false;

	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==POS_TAG)
		{
			file>>dstCam.camera.pos.x();
			file>>dstCam.camera.pos.y();
			file>>dstCam.camera.pos.z();

			posOk=true;
		}
		if (buffer==LOOK_TAG)
		{
			file>>dstCam.camera.look.x();
			file>>dstCam.camera.look.y();
			file>>dstCam.camera.look.z();

			dirOk=true;
		}
		if (buffer==RIGHT_TAG)
		{
			file>>dstCam.camera.right.x();
			file>>dstCam.camera.right.y();
			file>>dstCam.camera.right.z();

			rightOk=true;
		}

		if (buffer==NAME_TAG)
		{
			file>>dstCam.name;
		}
	}

	//assert(posOk && dirOk && rightOk);

	if ( ! ( posOk && dirOk && rightOk ) )
	{
		throw BasicException( "Position, direction or right vector was not set in Camera parameter" );
	}
}
void CALReader::parseOmni( fstream &file, LightCAL &dstLight )
{
	bool posOk=false;
	bool colorOk=false;
	bool intensityOk=false;
	bool attenuationOk=false;
			
	OmniLightPhong *omni= new OmniLightPhong();


	dstLight.lightPtr = omni;

	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==NAME_TAG)
		{
			file>>dstLight.name;
		}
		if (buffer==POS_TAG)
		{
			file>>omni->position.x();
			file>>omni->position.y();
			file>>omni->position.z();

			posOk=true;
		}
		if (buffer==COLOR_TAG)
		{
			file>>omni->color[0];
			file>>omni->color[1];
			file>>omni->color[2];

			colorOk=true;
		}
		if (buffer==INTENSITY_TAG)
		{
			file>>omni->intensity;
			intensityOk=true;
		}
		if (buffer==ATTENUATION_TAG)
		{
			file>>omni->attenuationExp;
			attenuationOk=true;
		}
	}

	//assert(posOk && colorOk );
	if ( ! ( posOk && colorOk && intensityOk && attenuationOk) )
	{
		delete omni;
		throw BasicException( "Position, color, intensity or attenuation was not set in Omnilight parameter" );
	}
}
void CALReader::parseSpot( fstream &file, LightCAL &dstLight )
{
	bool posOk=false;
	bool dirOk=false;
	bool colorOk=false;
	bool intensityOk=false;
	bool attenuationOk=false;
	bool directionalOk=false;

	SpotLightPhong *spot= new SpotLightPhong();
	dstLight.lightPtr = spot;

	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==NAME_TAG)
		{
			file>>dstLight.name;
		}

		if (buffer==POS_TAG)
		{
			file>>spot->position.x();
			file>>spot->position.y();
			file>>spot->position.z();

			posOk=true;
		}
		if (buffer==DIR_TAG)
		{
			file>>spot->direction.x();
			file>>spot->direction.y();
			file>>spot->direction.z();

			dirOk=true;
		}
		if (buffer==COLOR_TAG)
		{
			file>>spot->color[0];
			file>>spot->color[1];
			file>>spot->color[2];

			colorOk=true;
		}
		if (buffer==INTENSITY_TAG)
		{
			file>>spot->intensity;

			intensityOk=true;
		}	
		if (buffer==ATTENUATION_TAG)
		{
			file>>spot->attenuationExp;
			attenuationOk=true;
		}
		if (buffer==DIRECTIONAL_EXP_TAG)
		{
			file>>spot->directionalExp;
			directionalOk=true;
		}

	}


	if (! (posOk && dirOk && colorOk && intensityOk && attenuationOk && directionalOk ) )
	{
		delete spot;
		throw BasicException( "Position, direction, color, intensity, attenuation or directional was not set in Spotlight parameter" );
	}
}
void CALReader::parseSpotVRML( fstream &file, LightCAL &dstLight )
{
	bool posOk=false;
	bool dirOk=false;
	bool colorOk=false;
	bool intensityOk=false;
	bool innerOk=false;
	bool outerOk=false;
	bool attenuationOk = false;
		

	SpotLightPhongVRML *spotVRML= new SpotLightPhongVRML();
	dstLight.lightPtr = spotVRML;

	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==POS_TAG)
		{
			file>>spotVRML->position.x();
			file>>spotVRML->position.y();
			file>>spotVRML->position.z();

			posOk=true;
		}
		if (buffer==DIR_TAG)
		{
			file>>spotVRML->direction.x();
			file>>spotVRML->direction.y();
			file>>spotVRML->direction.z();

			dirOk=true;
		}
		if (buffer==COLOR_TAG)
		{
			file>>spotVRML->color[0];
			file>>spotVRML->color[1];
			file>>spotVRML->color[2];
			colorOk=true;
		}
		if (buffer==INTENSITY_TAG)
		{
			file>>spotVRML->intensity;
			intensityOk=true;
		}
		if (buffer==INNER_TAG)
		{
			file>>spotVRML->innerConeCos;
			innerOk=true;
		}
		if (buffer==OUTER_TAG)
		{
			file>>spotVRML->outerConeCos;
			outerOk=true;
		}
		if (buffer==NAME_TAG)
		{
			file>>dstLight.name;
		}
		if (buffer==ATTENUATION_TAG)
		{
			file>>spotVRML->attenuationExp;
			attenuationOk = true;
		}

	}

	//assert(posOk && dirOk && colorOk && innerOk && outerOk);
	if (! (posOk && dirOk && colorOk && intensityOk && innerOk && outerOk && attenuationOk) )
	{
		throw BasicException( "Position, direction, color, intensity, inner, outer cutoff angle or attenuation was not set in SpotlightVRML parameter" );
	}
}
void CALReader::parseRectangle( fstream &file, LightCAL &dstLight )
{
	bool posOk=false;
	bool colorOk=false;
	bool intensityOk=false;
	bool attenuationOk=false;
	bool vec1Ok=false;
	bool vec2Ok=false;
	bool directionalOk=false;

	RectangleLightPhong *rect= new RectangleLightPhong();
	dstLight.lightPtr = rect;

	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==NAME_TAG)
		{
			file>>dstLight.name;
		}
		if (buffer==POS_TAG)
		{
			file>>rect->position.x();
			file>>rect->position.y();
			file>>rect->position.z();

			posOk=true;
		}
		if (buffer==COLOR_TAG)
		{
			file>>rect->color[0];
			file>>rect->color[1];
			file>>rect->color[2];

			colorOk=true;
		}
		if (buffer==INTENSITY_TAG)
		{
			file>>rect->intensity;
			intensityOk=true;
		}
		if (buffer==ATTENUATION_TAG)
		{
			file>>rect->attenuationExp;
			attenuationOk=true;
		}
		if (buffer==VEC1_TAG)
		{
			file>>rect->vec1.x();
			file>>rect->vec1.y();
			file>>rect->vec1.z();
			vec1Ok=true;
		}
		if (buffer==VEC2_TAG)
		{
			file>>rect->vec2.x();
			file>>rect->vec2.y();
			file>>rect->vec2.z();
			vec2Ok=true;
		}
			
		if (buffer==DIRECTIONAL_EXP_TAG)
		{
			file>>rect->directionalExp;
			directionalOk=true;
		}
	}

	//assert(posOk && colorOk );
	if ( ! ( posOk && colorOk && intensityOk && attenuationOk && vec1Ok && vec2Ok && directionalOk) )
	{
		delete rect;
		throw BasicException( "Position, color, intensity, attenuation, vec1, vec2 or directionalExp was not set in Omnilight parameter" );
	}
}
void CALReader::parseDirectional( fstream &file, LightCAL &dstLight )
{
	bool posOk=false;
	bool colorOk=false;
	bool intensityOk=false;
	bool attenuationOk=false;
	bool vec1Ok=false;
	bool vec2Ok=false;

	DirectionalLightPhong *direct= new DirectionalLightPhong();


	dstLight.lightPtr = direct;

	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==NAME_TAG)
		{
			file>>dstLight.name;
		}
		if (buffer==POS_TAG)
		{
			file>>direct->position.x();
			file>>direct->position.y();
			file>>direct->position.z();

			posOk=true;
		}
		if (buffer==COLOR_TAG)
		{
			file>>direct->color[0];
			file>>direct->color[1];
			file>>direct->color[2];

			colorOk=true;
		}
		if (buffer==INTENSITY_TAG)
		{
			file>>direct->intensity;
			intensityOk=true;
		}
		if (buffer==ATTENUATION_TAG)
		{
			file>>direct->attenuationExp;
			attenuationOk=true;
		}
		if (buffer==VEC1_TAG)
		{
			file>>direct->vec1.x();
			file>>direct->vec1.y();
			file>>direct->vec1.z();
			vec1Ok=true;
		}
		if (buffer==VEC2_TAG)
		{
			file>>direct->vec2.x();
			file>>direct->vec2.y();
			file>>direct->vec2.z();
			vec2Ok=true;
		}
			
	}

	//assert(posOk && colorOk );
	if ( ! ( posOk && colorOk && intensityOk && attenuationOk && vec1Ok && vec2Ok) )
	{
		delete direct;
		throw BasicException( "Position, color, intensity, attenuation, vec1 or vec2 was not set in Omnilight parameter" );
	}
}
/*
void CALReader::parseDTIT( fstream &file, LightCAL &dstLight )
{
	DTITLight *dtitLight= new DTITLight();


	dstLight.lightPtr = dtitLight;

	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==SUBTYPE_TAG)
		{
			string subtype;
			file>> subtype;

			if ( subtype == OMNI_TAG)
			{
				dtitLight->subtype = OMNI_PHONG;
			}
			else if ( subtype == SPOT_TAG)
			{
				dtitLight->subtype = SPOT_PHONG;
			}
			else if ( subtype == RECTANGLE_TAG)
			{
				dtitLight->subtype = RECTANGLE_PHONG;
			}
			else if ( subtype == DIRECTIONAL_TAG)
			{
				dtitLight->subtype = DIRECTIONAL_PHONG;
			}
			else
			{
				assert( !"Unsupported lightype"); 
			}

		}
		if (buffer==KEYLIGHT_TAG)
		{
			file>>dtitLight->isKeyLight;
		}
		if (buffer==AO_TAG)
		{
			file>>dtitLight->multiplyByAmbientOcclusion;
		}
		if (buffer==SHADOW_TAG)
		{
			file>>dtitLight->castShadow;
		}
		if ( buffer == INDIRECT_TAG)
		{
			file>>dtitLight->indirectFactor;
		}
	
		if (buffer==DIRECTIONAL_EXP_TAG)
		{
			file>>dtitLight->directionalExp;
		}
		if (buffer==NAME_TAG)
		{
			file>>dstLight.name;
		}
		if (buffer==POS_TAG)
		{
			file>>dtitLight->position.x();
			file>>dtitLight->position.y();
			file>>dtitLight->position.z();
		}
		if (buffer==COLOR_TAG)
		{
			file>>dtitLight->color[0];
			file>>dtitLight->color[1];
			file>>dtitLight->color[2];
		}
		if (buffer==INTENSITY_TAG)
		{
			file>>dtitLight->intensity;
		}
		if (buffer==ATTENUATION_TAG)
		{
			file>>dtitLight->attenuation;
		}
		if (buffer==DIR_TAG)
		{
			file>>dtitLight->direction.x();
			file>>dtitLight->direction.y();
			file>>dtitLight->direction.z();
		}
		if (buffer==TANGENT_TAG)
		{
			file>>dtitLight->tangent.x();
			file>>dtitLight->tangent.y();
			file>>dtitLight->tangent.z();
		}
		if (buffer==BITANGENT_TAG)
		{
			file>>dtitLight->bitangent.x();
			file>>dtitLight->bitangent.y();
			file>>dtitLight->bitangent.z();
		}
		

			
	}
}
*/

void CALReader::parseMaterial(  fstream &file, MaterialCAL &dstMaterial )
{
	bool nameOk=false;
	bool pathOk=false;


	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==NAME_TAG)
		{
			file>>dstMaterial.name;

			nameOk=true;
		}
		if (buffer==PATH_TAG)
		{
			file>>dstMaterial.path;

			pathOk=true;
		}
	}

	//assert(nameOk && pathOk );
	if ( ! (nameOk && pathOk ) )
	{
		throw BasicException( "Name or path was not set in Material parameter" );
	}
}

void CALReader::parseModel( fstream &file, ModelCAL& dstModel )
{
	bool pathOk=false;
			
	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==NAME_TAG)
		{
			file>>dstModel.name;
		}
		if (buffer==PATH_TAG)
		{
			file>>dstModel.path;
			pathOk=true;
		}
		if (buffer==MATERIAL_TAG)
		{
			file>>dstModel.material;
		}
		if (buffer==MATRIX_TAG)
		{
			for (int i=0; i<16; ++i)
			{
				file>>*(dstModel.matrix.getPtr()+i);
			}
		}
	}

	if ( ! pathOk )
	{
		throw BasicException( "Name was not set in Model parameter" );
	}
}

void CALReader::parseTexture( fstream &file, TextureCAL& dstTexture )
{
	bool pathOk=false;
			
	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==NAME_TAG)
		{
			file>>dstTexture.name;
		}
		if (buffer==PATH_TAG)
		{
			file>>dstTexture.path;
			pathOk=true;
		}
	}

	if ( ! pathOk )
	{
		throw BasicException( "Name was not set in Texture parameter" );
	}
}

void CALReader::parseSkybox( fstream &file, SkyboxCAL& dstSkybox )
{
	bool frontOk=false;
	bool backOk=false;
	bool topOk=false;
	bool bottomOk=false;
	bool leftOk=false;
	bool rightOk=false;
	bool nameOk=false;

	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==NAME_TAG)
		{
			file>>dstSkybox.name;
			nameOk = true;
		}
		/*
		FRONT_TAG="FRONTTEXTURE";
		BACK_TAG="BACKTEXTURE";
		LEFT_TAG="LEFTTEXTURE";
		RIGHT_TAG="RIGHTTEXTURE";
		FRONT_TAG="TOPTEXTURE";
		FRONT_TAG="BOTTOMTEXTURE"
		*/
		if (buffer==FRONT_TEX_TAG)
		{
			file>>dstSkybox.front;
			frontOk=true;
		}
		if (buffer==BACK_TEX_TAG)
		{
			file>>dstSkybox.back;
			backOk=true;
		}
		if (buffer==LEFT_TEX_TAG)
		{
			file>>dstSkybox.left;
			leftOk=true;
		}
		if (buffer==RIGHT_TEX_TAG)
		{
			file>>dstSkybox.right;
			rightOk=true;
		}
		if (buffer==TOP_TEX_TAG)
		{
			file>>dstSkybox.top;
			topOk=true;
		}
		if (buffer==BOTTOM_TEX_TAG)
		{
			file>>dstSkybox.bottom;
			bottomOk=true;
		}
	}

	if ( ! (nameOk && topOk && bottomOk && rightOk && leftOk && frontOk && backOk) )
	{
		throw BasicException( "One or more skybox parameter was not set!" );
	}
}
void CALReader::parseTerrain( fstream &file, TerrainCAL& dstTerrain )
{
	bool geometryTexPatternOk=false;
	bool surfaceTexNameOk=false;
	bool materialNameOk=false;
	bool skyboxNameOk=false;
	bool cloudsTexNameOk=false;
	bool nameOk=false;

	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==NAME_TAG)
		{
			file>>dstTerrain.name;
			nameOk = true;
		}
		
		if (buffer==GEOMETRY_TAG)
		{
			file>>dstTerrain.geometryScript;
			geometryTexPatternOk=true;
		}
		if (buffer==SURFACE_TAG)
		{
			file>>dstTerrain.surfaceTexName;
			surfaceTexNameOk=true;
		}
		if (buffer==MATERIAL_TAG)
		{
			file>>dstTerrain.materialName;
			materialNameOk=true;
		}
		if (buffer==CLOUDS_TAG)
		{
			file>>dstTerrain.cloudsTexName;
			cloudsTexNameOk=true;
		}
		if (buffer==SKYBOX_TAG)
		{
			file>>dstTerrain.skyboxName;
			skyboxNameOk=true;
		}
	}

	if ( ! (nameOk && geometryTexPatternOk && surfaceTexNameOk && materialNameOk && cloudsTexNameOk && skyboxNameOk) )
	{
		throw BasicException( "One or more terrain parameter was not set!" );
	}
}

void CALReader::parseGraphicGenerator( fstream &file, GraphicGeneratorCAL &dstGraphic )
{
	bool nameOk=false;

	string buffer;
	while (buffer!=TYPE_TAG && !file.eof())
	{
		file>>buffer;
		toUpperCase(buffer);

		if (buffer==NAME_TAG)
		{
			file>>dstGraphic.name;
			nameOk = true;
		}

		if (buffer==BASELINE_TYPE_TAG)
		{
			unsigned int baselineType;
			file>>baselineType;
			dstGraphic.baselineTypes.push_back( baselineType );
		}

		if (buffer==GEOMETRY_TAG)
		{
			string geometryScript;
			file>>geometryScript;
			dstGraphic.terrainScripts.push_back( geometryScript );

		}
		if (buffer==INNER_SURFACE_TAG)
		{
			string surface;
			file>>surface;
			dstGraphic.innerSurfaceTexNames.push_back( surface );

		}
		if (buffer==OUTER_SURFACE_TAG)
		{
			string surface;
			file>>surface;
			dstGraphic.outerSurfaceTexNames.push_back( surface );

		}

		if (buffer==MATERIAL_TAG)
		{
			string material;
			file>>material;
			dstGraphic.materialNames.push_back( material );
		}
		if (buffer==CLOUDS_TAG)
		{
			string clouds;
			file>>clouds;
			dstGraphic.cloudNames.push_back( clouds );
		}
		if (buffer==SKYBOX_TAG)
		{
			string skybox;
			file>>skybox;
			dstGraphic.skyboxNames.push_back( skybox );
		}
	}

	if ( !nameOk  )
	{
		throw BasicException( "One or more parseGraphicGenerator parameter was not set!" );
	}
}

void CALReader::parseFile( void )
{
	string buffer;
	while ( !this->file.eof())
	{
		
		this->file>>buffer;
		toUpperCase(buffer);

		if (buffer==CAMERA_TAG)
		{
			CameraCAL cam;
			this->parseCamera(  this->file, cam);

			if ( this->dstCamera != NULL )
			{
				this->dstCamera->push_back(cam);
			}
		}
		if (buffer==OMNI_TAG)
		{
			LightCAL newLight;
			this->parseOmni(  this->file, newLight );

			if ( this->dstLight != NULL )
			{
				this->dstLight->push_back( newLight );
			}
		}
		if ( buffer==SPOT_TAG  )
		{
			LightCAL newLight;
			this->parseSpot(  this->file, newLight );
			
			if ( this->dstLight != NULL )
			{
				this->dstLight->push_back( newLight );
			}
		}
		if (  buffer== SPOT_VRML_TAG )
		{
			LightCAL newLight;
			this->parseSpotVRML(  this->file, newLight );
			
			if ( this->dstLight != NULL )
			{
				this->dstLight->push_back( newLight );
			}
		}
		if (buffer==RECTANGLE_TAG)
		{
			LightCAL newLight;
			this->parseRectangle(  this->file, newLight );
			
			if ( this->dstLight != NULL )
			{
				this->dstLight->push_back( newLight );
			}
		}
		if (buffer==DIRECTIONAL_TAG)
		{
			LightCAL newLight;
			this->parseDirectional( this->file, newLight );			
			
			if ( this->dstLight != NULL )
			{
				this->dstLight->push_back( newLight );
			}
		}
		if (buffer==MATERIAL_TAG)
		{
			MaterialCAL newMaterial;
			this->parseMaterial( this->file, newMaterial );
			
			if ( this->dstMaterial != NULL )
			{
				this->dstMaterial->push_back( newMaterial );
			}
		}
		if (buffer==MODEL_TAG)
		{
			ModelCAL newModel;
			this->parseModel( this->file, newModel );

			if ( this->dstModel != NULL )
			{
				this->dstModel->push_back(newModel);
			}
		}
		if (buffer==TEXTURE_TAG)
		{
			TextureCAL newTexture;
			this->parseTexture( this->file, newTexture );

			if ( this->dstTexture != NULL )
			{
				this->dstTexture->push_back(newTexture);
			}
		}
		if (buffer==SKYBOX_TAG)
		{
			SkyboxCAL newSkybox;
			this->parseSkybox( this->file, newSkybox );

			if ( this->dstSkybox != NULL )
			{
				this->dstSkybox->push_back(newSkybox);
			}
		}
		if (buffer==TERRAIN_TAG)
		{
			TerrainCAL newTerrain;
			this->parseTerrain( this->file, newTerrain );

			if ( this->dstTerrain != NULL )
			{
				this->dstTerrain->push_back(newTerrain);
			}
		}
		if (buffer==GRAPHIC_GENERATOR_DATABASE_TAG)
		{
			GraphicGeneratorCAL newGraphicSet;

			this->parseGraphicGenerator( this->file, newGraphicSet );

			if ( this->dstGraphicGeneratorContainer != NULL )
			{
				this->dstGraphicGeneratorContainer->push_back( newGraphicSet );
			}
		}

	}
}

void CALexporter::exportCamera( ofstream &file, CameraContainer &srcCamera )
{
	//store cameras
	for ( int i=0; i< srcCamera.size(); ++i)
	{
		file<< TYPE_TAG<< DELIMER_TAG << CAMERA_TAG << endl;
		file<< NAME_TAG<< DELIMER_TAG << srcCamera[i].name << endl;
		file<< POS_TAG<< DELIMER_TAG << srcCamera[i].camera.pos.x()<< DELIMER_TAG << srcCamera[i].camera.pos.y()<< DELIMER_TAG << srcCamera[i].camera.pos.z() <<endl;
		file<< LOOK_TAG<< DELIMER_TAG << srcCamera[i].camera.look.x()<< DELIMER_TAG << srcCamera[i].camera.look.y()<< DELIMER_TAG << srcCamera[i].camera.look.z() <<endl;
		file<< RIGHT_TAG<< DELIMER_TAG << srcCamera[i].camera.right.x()<< DELIMER_TAG << srcCamera[i].camera.right.y()<< DELIMER_TAG << srcCamera[i].camera.right.z() <<endl;
		file<< endl;
	}
}

void CALexporter::exportLight( ofstream &file, LightContainer &srcLight )
{
	//store lights
	for ( int i=0; i< srcLight.size(); ++i)
	{
		switch ( srcLight[i].lightPtr->getLightType() )
		{
			case OMNI_PHONG:
			{
				OmniLightPhong * omni = (OmniLightPhong*) srcLight[i].lightPtr;
				
				file<< TYPE_TAG<< DELIMER_TAG << OMNI_TAG << endl;
				file<< NAME_TAG<< DELIMER_TAG << srcLight[i].name << endl;
				file<< POS_TAG<< DELIMER_TAG << omni->position.x()<< DELIMER_TAG << omni->position.y()<< DELIMER_TAG << omni->position.z() <<endl;
				file<< COLOR_TAG<< DELIMER_TAG << omni->color[0]<< DELIMER_TAG << omni->color[1]<< DELIMER_TAG << omni->color[2] <<endl;
				file<< INTENSITY_TAG<< DELIMER_TAG << omni->intensity <<endl;
				file<< ATTENUATION_TAG<< DELIMER_TAG << omni->attenuationExp <<endl;
			}
			break;

			case SPOT_PHONG:
			{
				SpotLightPhong * spot = (SpotLightPhong*) srcLight[i].lightPtr;
				
				file<< TYPE_TAG<< DELIMER_TAG << SPOT_TAG << endl;
				file<< NAME_TAG<< DELIMER_TAG << srcLight[i].name << endl;
				file<< POS_TAG<< DELIMER_TAG << spot->position.x()<< DELIMER_TAG << spot->position.y()<< DELIMER_TAG << spot->position.z() <<endl;
				file<< COLOR_TAG<< DELIMER_TAG << spot->color[0]<< DELIMER_TAG << spot->color[1]<< DELIMER_TAG << spot->color[2] <<endl;
				file<< INTENSITY_TAG<< DELIMER_TAG << spot->intensity <<endl;
				file<< ATTENUATION_TAG<< DELIMER_TAG << spot->attenuationExp <<endl;
				file<< DIR_TAG<< DELIMER_TAG << spot->direction.x()<< DELIMER_TAG<<spot->direction.y()<< DELIMER_TAG<<spot->direction.z() <<endl;
				file<<DIRECTIONAL_EXP_TAG<< DELIMER_TAG<< spot->directionalExp << endl;
			}
			break;

			case RECTANGLE_PHONG:
			{
				RectangleLightPhong * rect = (RectangleLightPhong*) srcLight[i].lightPtr;
				
				file<< TYPE_TAG<< DELIMER_TAG << RECTANGLE_TAG << endl;
				file<< NAME_TAG<< DELIMER_TAG << srcLight[i].name << endl;
				file<< POS_TAG<< DELIMER_TAG << rect->position.x()<< DELIMER_TAG << rect->position.y()<< DELIMER_TAG << rect->position.z() <<endl;
				file<< COLOR_TAG<< DELIMER_TAG << rect->color[0]<< DELIMER_TAG << rect->color[1]<< DELIMER_TAG << rect->color[2] <<endl;
				file<< INTENSITY_TAG<< DELIMER_TAG << rect->intensity <<endl;
				file<< ATTENUATION_TAG<< DELIMER_TAG << rect->attenuationExp <<endl;
				file<< VEC1_TAG<< DELIMER_TAG << rect->vec1.x()<<DELIMER_TAG<< rect->vec1.y() <<DELIMER_TAG<< rect->vec1.z() <<endl;
				file<< VEC2_TAG<< DELIMER_TAG << rect->vec2.x()<<DELIMER_TAG<< rect->vec2.y() <<DELIMER_TAG<< rect->vec2.z() <<endl;
				file<<DIRECTIONAL_EXP_TAG<< DELIMER_TAG<< rect->directionalExp << endl;
			}
			break;

			case DIRECTIONAL_PHONG:
			{
				DirectionalLightPhong * direct = (DirectionalLightPhong*) srcLight[i].lightPtr;
				
				file<< TYPE_TAG<< DELIMER_TAG << DIRECTIONAL_TAG << endl;
				file<< NAME_TAG<< DELIMER_TAG << srcLight[i].name << endl;
				file<< POS_TAG<< DELIMER_TAG << direct->position.x()<< DELIMER_TAG << direct->position.y()<< DELIMER_TAG << direct->position.z() <<endl;
				file<< COLOR_TAG<< DELIMER_TAG << direct->color[0]<< DELIMER_TAG << direct->color[1]<< DELIMER_TAG << direct->color[2] <<endl;
				file<< INTENSITY_TAG<< DELIMER_TAG << direct->intensity <<endl;
				file<< ATTENUATION_TAG<< DELIMER_TAG << direct->attenuationExp <<endl;
				file<< VEC1_TAG<< DELIMER_TAG << direct->vec1.x()<<DELIMER_TAG<< direct->vec1.y() <<DELIMER_TAG<< direct->vec1.z() <<endl;
				file<< VEC2_TAG<< DELIMER_TAG << direct->vec2.x()<<DELIMER_TAG<< direct->vec2.y() <<DELIMER_TAG<< direct->vec2.z() <<endl;
			}
			break;

			default:
				assert( !"Unsuported light type!");
			break;
		}
		file<<endl;
	}
}

void CALexporter::exportMaterial( ofstream &file, MaterialContainer &srcMaterial )
{
	//store materials
	for ( int i=0; i< srcMaterial.size(); ++i)
	{
		file<< TYPE_TAG<< DELIMER_TAG << MATERIAL_TAG << endl;
		file<< NAME_TAG<< DELIMER_TAG << srcMaterial[i].name << endl;
		file<< PATH_TAG<< DELIMER_TAG << srcMaterial[i].path << endl;
		file<< endl;
	}
}

void CALexporter::exportModel( ofstream &file, ModelContainer &srcModel )
{
	//store models
	for ( int i=0; i< srcModel.size(); ++i)
	{
		file<< TYPE_TAG<< DELIMER_TAG << MODEL_TAG << endl;
		file<< NAME_TAG<< DELIMER_TAG << srcModel[i].name << endl;
		file<< PATH_TAG<< DELIMER_TAG << srcModel[i].path << endl;
		file<< MATERIAL_TAG<< DELIMER_TAG << srcModel[i].material << endl;
		file<< MATRIX_TAG;
			for ( int n=0; n<16; ++n )
			{
				file<< DELIMER_TAG <<srcModel[i].matrix[n];
			}
		file<< endl<< endl;
	}
}


void CALexporter::exportToCAL( ofstream &file, CameraContainer &srcCamera, LightContainer &srcLight, MaterialContainer &srcMaterial, ModelContainer &srcModel )
{
	CALexporter::exportCamera( file, srcCamera );
	CALexporter::exportLight( file, srcLight );
	CALexporter::exportMaterial( file, srcMaterial );
	CALexporter::exportModel( file, srcModel );
}

void CALexporter::exportToCAL(const string &fileName, CameraContainer &srcCamera, LightContainer &srcLight, MaterialContainer &srcMaterial, ModelContainer &srcModel )
{
	ofstream file;
	file.open( fileName );

	if ( file.fail() )
	{
		throw FileException( fileName );
	}

	exportToCAL( file, srcCamera, srcLight, srcMaterial, srcModel );
}

}