#pragma once

#include <C2/gl/GlDisplayList.h>

#include "SceneMain.h"
#include "View3DConfig.h"

#include "ShaderLibrary.h"

#include <LibQtGeoViewerCore/GeomObject.h>
#include <LibQtGeoViewerCore/VBOHelper.h>



class GeometryRender
{
private:
	enum MeshRenderMode
	{
		MR_FILL,
		MR_WIRE_SHADE,
		MR_WIRE_OVERLAY,
	};

public:
	GeometryRender(void);
	virtual ~GeometryRender(void);

	void InitializeRender(View3DConfig* config, ShaderLibrary* shaders);

	void ReleaseAccBuffer(void);

	void DrawGeomVertPick(GeomObject& obj, SceneMain& scene);
	void DrawGeomHighlight(GeomObject& obj, SceneMain& scene);

	void DrawFace_WireConstantColor(GeomObject& obj, SceneMain& scene);
	void DrawFace_WireConstantColorForCS(GeomObject& obj, SceneMain& scene);
	void DrawFace_WireConstantColorVBO(GeomObject& obj, SceneMain& scene);
	void DrawFace_WireConstantColorRawOrDispList(GeomObject& obj, SceneMain& scene);
	void DrawFace_Fill(GeomObject& obj, SceneMain& scene, ShaderInterface* shader);

	void DrawMeshMain(GeomObject& obj, SceneMain& scene, ShaderInterface* shader);
	void DrawFaceIndexColor(GeomObject& obj, SceneMain& scene, unsigned int idx);

	void DrawMeshExtAll(GeomObject& obj);
	void DrawSelVertAll(GeomObject& obj);

private:
	void DrawMeshFaceMain(GeomObject& obj, SceneMain& scene, ShaderInterface* shader, MeshRenderMode mode);

	void DrawMeshFid(lib_geo::BaseMesh& mesh);

	void DrawVertPoint(const lib_geo::BaseMesh& mesh);
	void DrawVertVid(GeomObject& obj);
	void DrawVertNormal(const lib_geo::BaseMesh& mesh, float LineLen);

	void SetGLNormalColor(const lm::vec3f& n) const;

	void AssignMaterialToFace(SceneMain& scene, GeomObject& obj, ShaderInterface* shader, const lib_geo::BaseFace& f, bool IsHilightMat) const;
	const lib_graph::Material* GetFaceMaterial(SceneMain& scene, const GeomObject& geom, const lib_geo::BaseFace& f) const;
	void AssinTextures(SceneMain& scene, GeomObject& obj, ShaderInterface* shader, const lib_geo::BaseFace& f) const;
	void AssignMatcap(SceneMain& scene, GeomObject& obj, ShaderInterface* shader, const lib_geo::BaseFace& f) const;
	void AssignShadowmap(SceneMain& scene, GeomObject& obj, ShaderInterface* shader, const lib_geo::BaseFace& f) const;
	gl::GlTexture* GetFaceTexture(SceneMain& scene, GeomObject& obj, const lib_geo::BaseFace& f) const;

	void DrawFaceGroupGeometry(lib_geo::BaseMesh& mesh, const FaceGroup& fg, GLenum primitive_type);
	GeometryVBO* GetOrCreateVBO(lib_geo::BaseMesh& mesh, const FaceGroup& fg);

	void SetGlIndexColor(unsigned int idx) const;

private:
	GeometryRender(const GeometryRender&) {}
	void operator=(const GeometryRender&) {}

	bool IsVisibleObject(const SceneMain& scene, const GeomObject& obj) const;

private:
	View3DConfig* m_Config;
	ShaderLibrary* m_Shaders;

	View3DConfig m_LastConfig;
	lib_gl::GlDisplayList m_DispList_FaceWire;
	lib_gl::GlDisplayList m_DispList_Vert;
	lib_gl::GlDisplayList m_DispList_Vid;
	lib_gl::GlDisplayList m_DispList_Fid;

	std::map<int, GeometryVBO> m_FaceGroupVBO;
};
