#include <vector>
#include <algorithm>
#include <cassert>

using namespace std;

#ifndef MODEL_STORAGE_H
#define MODEL_STORAGE_H

typedef unsigned int GL_ID;

typedef vector<float> vcoord_buffer;
typedef vector<float> tcoord_buffer;
typedef vector<float> ncoord_buffer;

typedef vector<vector<int>> fv_coord_buffer;
typedef vector<vector<int>> ft_coord_buffer;
typedef vector<vector<int>> fn_coord_buffer;

typedef vector<vector<int>> funion_coord_buffer;

typedef vector<vector<int>> triangle_f_coord_buffer;

///Auxiliary mesh data storage structure
class Model_storage
{
protected:
	vcoord_buffer v_coords;
	tcoord_buffer t_coords;
	ncoord_buffer n_coords;

	fv_coord_buffer fv_coords;
	ft_coord_buffer ft_coords;
	fn_coord_buffer fn_coords;

public:
	virtual void pushVcoord(float x, float y, float z);
	virtual void pushTcoord(float x, float y);
	virtual void pushNcoord(float x, float y, float z);
	virtual void pushFcoord(const vector<int>& fvcoord, const vector<int>& fncoord, const vector<int>& ftcoord);

	vcoord_buffer&  getVcoordBuffer();
	tcoord_buffer&  getTcoordBuffer();
	ncoord_buffer&  getNcoordBuffer();
	fv_coord_buffer&  getFVcoordBuffer();
	ft_coord_buffer&  getFTcoordBuffer();
	fn_coord_buffer&  getFNcoordBuffer();
};



//triangulation methods
bool convertToTriangularFaces(const vector<vector<int>>& polygon_indices);
bool convertPolygonToTriangles(vector<int>& polygon_indices, vector<vector<int>>& dst_triangles_indices);
void convertPolygonsToTriangles( vector<vector<int>>& src_indices, vector<vector<int>>& dst_indices);
void convertPolygonsToTriangles( vector<vector<int>>& src_indices,unsigned int from, unsigned int to, vector<vector<int>>& dst_indices);



//conversion to union indices
void convertCoordsToUnionIndices(const fv_coord_buffer& fv_coords, const vcoord_buffer& vcoords, 
	const fn_coord_buffer& fn_coords, const ncoord_buffer& ncoords, 
	const ft_coord_buffer& ft_coords, const tcoord_buffer& tcoords, 
	vcoord_buffer& dst_union_vcoords, ncoord_buffer& dst_union_ncoords, tcoord_buffer& dst_union_tcoords, funion_coord_buffer& union_indices);



void getPolygonNcoords(const fn_coord_buffer& fn_coords, const ncoord_buffer& ncoords, int polygon_index, ncoord_buffer& dst_polygon_n);
void getPolygonTcoords(const ft_coord_buffer& ft_coords, const tcoord_buffer& tcoords, int polygon_index, tcoord_buffer& dst_polygon_t);
void getPolygonVcoords(const fv_coord_buffer& fv_coords, const vcoord_buffer& vcoords, int polygon_index, vcoord_buffer& dst_polygon_v);

void convertIndicesToArray1D(const vector<vector<int>>& src_indices, vector<int>& dst_array);



#endif