#pragma once
#include "Vector3D.h"
#include "Vertex.h"
#include "Polygon3D.h"
#include "Matrix.h"
#include "Camera.h"
#include "Texture.h"
#include "UVCoord.h"
#include <vector>
#include <algorithm>
#include <string>

using namespace std;

enum class DrawMethod { Wireframe, Flat, FlatRaster, Smooth, Textured };

class Model
{
public:
	Model();
	Model(string MD2Filename, string textureFilename);
	~Model();

	string GetModelFilename() const;
	const char* CGetModelFilename() const;
	string GetTextureFilename() const;
	const char* CGetTextureFilename() const;

	void SetActive(bool value);
	void ToggleActive();
	bool GetActive() const;

	void SetDrawMethod(DrawMethod method);
	DrawMethod GetDrawMethod() const;

	vector<Polygon3D>& GetPolygons(void);
	vector<Vertex>& GetVertices(void);
	vector<UVCoord>& GetUVCoords(void);
	const vector<Matrix>& GetPendingTransforms(void);

	size_t GetPolygonCount(void);
	size_t GetVerticesCount(void);
	size_t GetUVCoordCount(void);
	size_t GetPendingTransformCount(void);

	void AddVertex(float x, float y, float z);
	void AddPolygon(int index0, int index1, int index2, int uvIndex0, int uvIndex1, int uvIndex2);
	void AddTextureUV(float u, float v);
	void EnqueueTransform(Matrix transform);
	void ClearPendingTransforms();

	Texture& GetTexture();
	const Polygon3D& GetPolygon(int index) const;
	const Vertex& GetVertex(int polygonIndex, int vertexPolygonIndex) const;
	const Vertex& GetVertex(int index) const;
	const UVCoord& GetUVCoord(int index) const;

	vector<Vertex> GetPolygonVertexArray(int index) const;
	void SetPolygonColor(int index, COLORREF color);
	void SetVertexColor(int polyIndex, int vertIndex, COLORREF color);

	void SetReflectionCoefficient(float red, float green, float blue);
	void SetReflectionCoefficient(ColRef color, float value);
	void SetRedReflectionCoefficient(float value);
	void SetGreenReflectionCoefficient(float value);
	void SetBlueReflectionCoefficient(float value);

	float GetReflectionCoefficient(ColRef color) const;
	float GetRedReflectionCoefficient() const;
	float GetGreenReflectionCoefficient() const;
	float GetBlueReflectionCoefficient() const;

	void ApplyTransformToLocalVertices(const Matrix& transform);
	void ApplyTransformToTransformedVertices(const Matrix& transform);
	void DehomogenizeAllVertices(void);

	void CalculateBackfaces(Camera& currentCamera);
	void CalculateVertexNormals();
	void Sort(void);

private:
	vector<Polygon3D> _polygons;
	vector<Vertex> _vertices;
	vector<Vertex> _transformedVertices;
	vector<Matrix> _pendingTransforms;

	vector<UVCoord> _uvCoords;
	
	Texture _texture;

	float _kdRed;
	float _kdGreen;
	float _kdBlue;

	bool _active;
	DrawMethod _drawMethod;

	string _modelMD2Filename;
	string _modelTextureFilename;
};

