#ifndef __BVH_TOP_H__
#define __BVH_TOP_H__

#include "AbstractBVH.h"
#include "BVHBottom.h"
#include "MaterialCache.h"
#include "bvh.h"
#include "geometrynode.h"
#include "msgqueue.h"
#include "RayTracerCommon.h"
#include "SceneShadow.h"
#include "RTMaterial.h"

// remove accelerators for removed geometries
//#define CLEANUP_ACCELERATORS

namespace VRUT
{

	class BVHTop : public AbstractBVH
	{

	public:

		struct BVHNodeInfo
		{
			GEOMETRY_ID geometryID;
			Matrix worldMat;
			Matrix invWorldMat;
			RTMaterial *material;
			bool isMatUnit;
		};

		struct BVHCollapseNode
		{
			bool active;
			bool leaf;
			int offset;
			AABB box;
			BVHCollapseNode * left;
			BVHCollapseNode * right;
		};

	private:

		class GeometryAccRebuildQueueNode  : public MPMC_QueueNode
		{
		public:
			GeometryAccRebuildQueueNode(GEOMETRY_ID gid) : MPMC_QueueNode(), gid(gid) {}
			GEOMETRY_ID gid;
		};

		bool workersBuildgeoAcc;
#ifdef CLEANUP_ACCELERATORS
		bool resetGeometry;
#endif

		wxCriticalSection geometricAccBuildCriticalSection;

		std::vector<BVHBottom*> geometryAccelerators;
		std::vector<bool> resetGeometries;
		std::vector<BVHNodeInfo> bvhNodeInfos;
		MPMC_Queue<GeometryAccRebuildQueueNode> geometryAccRebuildQueue;

		float GetSubtreeCost(int index) const;
		BVHCollapseNode * CollapseNodes(BVHCollapseNode * node);
		void UpdateTopology(RayTracerBHV * bvh, SceneShadow * sceneShadow);
		size_t GetNumberOfTriangles(smart_pointer<Geometry> g);

	public:

		BVHTop(void);
		~BVHTop(void);

		void Update(RayTracerBHV * bvh, SceneShadow * sceneShadow, MaterialCache & materialCache);

		void DeleteGeometryCache(void);
		void InvalidateGeometryCacheEntry(unsigned int index);

		void WorkersBuildGeoAccStart(void);
		void WorkersBuildGeoAccStop(void);
		bool BuildGeomAcc(smart_pointer_v2<Scene> & scene, int optRatio, int optMaxIterations, int optThreshold, int optRandomThreshold);

		bool IsEmpty(void) const;
		float Radius(void) const;
		const std::vector<BVHNodeInfo> & GetNodeInfos(void) const;
		const std::vector<BVHBottom*> & GetGeomAccelerators(void) const;
	};

}

#endif /* __BVH_TOP_H__ */
