#ifndef MODEL_GROUP_STORAGE_H
#define MODEL_GROUP_STORAGE_H

#include "ModelStorage.h"
#include <map>

const string UNDEFINED_GROUP_NAME="@@__undefined_group_name__@@";

/// Defines group of interval ranges for some polygon model.
struct GroupInfo
{
	int from_v_coord_index; /**< vertex coordinates index: range from given index */
	int to_v_coord_index;	/**< vertex coordinates index: range to given index */

	int from_t_coord_index;	/**< texture coordinates index: range from given index */
	int to_t_coord_index;	/**< texture coordinates index: range to given index */

	int from_n_coord_index;	/**< normals coordinates index: range from given index */
	int to_n_coord_index;	/**< normals coordinates index: range to given index */

	int from_fv_coord_index;	/**< face vertex index: range from given index */
	int to_fv_coord_index;		/**< face vertex index: range to given index */

	int from_ft_coord_index;	/**< face texture index: range from given index */
	int to_ft_coord_index;		/**< face texture index: range to given index */

	int from_fn_coord_index;	/**< face normals index: range from given index */
	int to_fn_coord_index;		/**< face normals index: range to given index */

	bool finished;		/**< Flag if whole group of data is finished */

	GroupInfo(void);
};

///Auxiliary mesh group structure
struct InternalInfo
{
	string actual_group_name;

	bool has_group_name;

	int to_fn_coord_index;
	int to_ft_coord_index;
	int to_fv_coord_index;
	
	int to_v_coord_index;
	int to_t_coord_index;
	int to_n_coord_index;

	InternalInfo(void);
};

///Data for group of polygons
struct Group
{
	string group_name;
	string material_name;
	GroupInfo group_info;
};

typedef vector<Group> Group_data;

///Complex structure for storing complex polygon model data.
/**
*	Stores vertices, texture coords, normals and their face indices for complex polygon model.
*	Model can consist of one or more groups, where group is set of polygons with same material.
*/
class ModelGroupStorage: public Model_storage
{
private:
	Group_data groups;
	InternalInfo inter_info;

	Group_data::iterator findGroup(const string& group_name);
	Group_data::reverse_iterator rfindGroup(const string& group_name);

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>& ftcoord, const vector<int>& fncoord);

	void newGroup(const string& group_name);
	void newGroup(void);

	void setGroupName(const string& group_name);

	bool hasMaterialName( void );
	void setMaterialName(const string& group_name);

	void renameGroup(const string& old_group_name, const string& new_group_name);
	void finish_group(void);

	GroupInfo getGroupInfo(const string& group_name);
	void get_groups(vector<Group>& dst_groups);
};


#endif