// © Copyright 2008 Vladimir Frolov, Moscow State University Graphics & Media Lab
#pragma once

class BVH_Tree;
class KdTree;

#ifndef MGML_GUARDIAN
	#include "../CSL/MGML.h"
#endif

#include "IGraphicsEngine.h"

//#ifndef HIERARCHICAL_GRID_GUARDIAN
//  #include "HierarchicalGrid.h"
//#endif

#include <memory>
#include <string>

using namespace MGML;
using namespace RAYTR;

class DLL_API Common_Graphics_Engine : public IGraphicsEngine,
							                         public MGML_MATH::SSE_Aligned_Object
{
public:

	typedef unsigned int uint;

  Common_Graphics_Engine(int w,int h);
	~Common_Graphics_Engine();

	void BuildAccelerationStructures(uint in_maxNodes = IGraphicsEngine::MAX_KD_TREE_NODES);

	vec2ui AddTriangles(const Vertex4f* v,int N_vertices,
					            const unsigned int* indices,int N_indices);
	unsigned int AddSpheres(const Sphere4f* s,int N_spheres);
	uint AddPointLight(const RAYTR::PointLight& light);
  uint AddFlatLight(const FlatLight& light);

	uint AddTexture(const void* memory,uint w,uint h,uint format);

	virtual uint	AddScene();
	virtual void	SetActiveScene(uint scnIndex);

	void SetPointLight(const RAYTR::PointLight& light,int index);
  void SetFlatLight(const FlatLight& light,int index);	
  void SetMaterial(const RAYTR::Material& mat, unsigned int N);

	void SetCamMatrix(const Matrix4x4f& mat);
  void MoveCam(const vec4f& pos);

	unsigned int AddMaterial(const RAYTR::Material& mat);

	const RAYTR::PointLight&	GetPointLight(int index) const;
	const RAYTR::Material&		GetMaterial(int index) const;
	const Matrix4x4f&	GetCamMatrix() const;

  BVH_Tree* GetBVHTree() { return m_bvhTree; }

  void DebugDrawAccelStruct();

protected:

  virtual void DrawLights();

  Matrix4x4f* pWorld_matrix;

	UINT*		 screen_buffer;
	int			 width;
	int			 height;

	RAYTR::Material*	  materials;
	int			    num_mat;

	Image*      textures;
	int			    num_textures;

	KdTree*     kd_tree;
  KdTree*     m_photonsKdTree;
  BVH_Tree*   m_bvhTree;

  AccelerationStructure* m_pAccelStruct;

  RAYTR::PointLight* point_lights;
	int         num_point_lights;

  FlatLight* m_flatLights;
  int        m_numFlatLights;
	
	Sphere4f*	  spheres; 
	int			    num_sph;
  int         max_num_sph;
	
	Vertex4f*   vert;
	int			    num_vert;

	UINT*		    index;
	int			    num_ind;

	unsigned int currScnIndex;
	unsigned int scnTop;
  bool m_camMatrixWasSet;

  float m_gatherRadius;

};

extern DLL_API Ray3f g_debugRay;