
#include "modelGroupStorage.h"
#include <string>

GroupInfo::GroupInfo(void)
{
	this->from_v_coord_index=-1;
	this->to_v_coord_index=-1;

	this->from_t_coord_index=-1;
	this->to_t_coord_index=-1;

	this->from_n_coord_index=-1;
	this->to_n_coord_index=-1;

	this->from_fv_coord_index=-1;
	this->to_fv_coord_index=-1;

	this->from_ft_coord_index=-1;
	this->to_ft_coord_index=-1;

	this->from_fn_coord_index=-1;
	this->to_fn_coord_index=-1;

	this->finished=false;
}

InternalInfo::InternalInfo(void)
{
	this->has_group_name=false;

	this->to_fn_coord_index=0;
	this->to_ft_coord_index=0;
	this->to_fv_coord_index=0;

	this->to_v_coord_index=0;
	this->to_n_coord_index=0;
	this->to_t_coord_index=0;
}

void ModelGroupStorage::finish_group(void)
{
	if (!this->groups.empty())
	{
		//TIP: maybe only .back() can we called instead of find(NAME);
		//find my group ( we search in reverse order because more groups may have the same name and in this case the last group with such name is our )
		Group_data::reverse_iterator it=this->rfindGroup(this->inter_info.actual_group_name);

		if (!it->group_info.finished)
		{
			it->group_info.to_fn_coord_index=this->inter_info.to_fn_coord_index;
			it->group_info.to_ft_coord_index=this->inter_info.to_ft_coord_index;
			it->group_info.to_fv_coord_index=this->inter_info.to_fv_coord_index;

			it->group_info.to_v_coord_index=this->inter_info.to_v_coord_index;
			it->group_info.to_t_coord_index=this->inter_info.to_t_coord_index;
			it->group_info.to_n_coord_index=this->inter_info.to_n_coord_index;

			it->group_info.finished=true;
		}
	}
}


void ModelGroupStorage::setGroupName(const string& group_name)
{
	this->groups.back().group_name=group_name; 
	this->inter_info.actual_group_name=group_name;
	this->inter_info.has_group_name=true;
}

void ModelGroupStorage::setMaterialName(const string& material_name)
{
	this->groups.back().material_name=material_name;
}
bool ModelGroupStorage::hasMaterialName( void )
{
	return !this->groups.back().material_name.empty();
}
void ModelGroupStorage::newGroup(void)
{
	this->newGroup(UNDEFINED_GROUP_NAME);

	this->inter_info.has_group_name=false;
}
void ModelGroupStorage::newGroup(const string& group_name)
{
	this->finish_group();

	this->inter_info.actual_group_name=group_name;
	this->inter_info.has_group_name=true;

	GroupInfo new_group_info;

	new_group_info.from_fn_coord_index=this->inter_info.to_fn_coord_index;
	new_group_info.from_ft_coord_index=this->inter_info.to_ft_coord_index;
	new_group_info.from_fv_coord_index=this->inter_info.to_fv_coord_index;

	new_group_info.from_n_coord_index=this->inter_info.to_n_coord_index;
	new_group_info.from_v_coord_index=this->inter_info.to_v_coord_index;
	new_group_info.from_t_coord_index=this->inter_info.to_t_coord_index;

	Group newGroup;
	newGroup.group_name=group_name;
	newGroup.group_info=new_group_info;
	this->groups.push_back(newGroup);
}

Group_data::iterator ModelGroupStorage::findGroup(const string& group_name)
{
	Group_data::iterator it=this->groups.begin();

	for (; it!=this->groups.end() ; ++it)
	{
		if (it->group_name==group_name)
		{
			return it;
		}
	}	
	return it;
}

Group_data::reverse_iterator ModelGroupStorage::rfindGroup(const string& group_name)
{
	Group_data::reverse_iterator it=this->groups.rbegin();

	for (; it!=this->groups.rend() ; ++it)
	{
		if (it->group_name==group_name)
		{
			return it;
		}
	}	
	return it;
}

void ModelGroupStorage::renameGroup(const string& old_group_name, const string& new_group_name)
{
	Group_data::iterator it=this->findGroup(old_group_name);

	this->inter_info.actual_group_name=new_group_name;	//POZOR old_group_name muze byt reference na actual_group_name ...proto prikaz1 musi byt PRED timto prikazem!!!

	if (it!=this->groups.end())
	{
		it->group_name=new_group_name;
	}
}

GroupInfo ModelGroupStorage::getGroupInfo(const string& group_name)
{
	
	GroupInfo group_info;

	Group_data::iterator it=this->findGroup(group_name);

	if (it!=this->groups.end())
	{
		group_info=it->group_info;
	}
	else
	{
		throw exception("Unkown group name!");
	}

	if (!group_info.finished)
	{
		group_info.to_fn_coord_index=this->inter_info.to_fn_coord_index;
		group_info.to_ft_coord_index=this->inter_info.to_ft_coord_index;
		group_info.to_fv_coord_index=this->inter_info.to_fv_coord_index;

		group_info.to_v_coord_index=this->inter_info.to_v_coord_index;
		group_info.to_t_coord_index=this->inter_info.to_t_coord_index;
		group_info.to_n_coord_index=this->inter_info.to_n_coord_index;
	}

	return group_info;
}

void ModelGroupStorage::pushVcoord(float x, float y, float z)
{
	Model_storage::pushVcoord(x,y,z);

	++this->inter_info.to_v_coord_index;
}
void ModelGroupStorage::pushTcoord(float x, float y)
{
	Model_storage::pushTcoord(x,y);

	++this->inter_info.to_t_coord_index;
}
void ModelGroupStorage::pushNcoord(float x, float y, float z)
{
	Model_storage::pushNcoord(x,y,z);

	++this->inter_info.to_n_coord_index;
}
void ModelGroupStorage::pushFcoord(const vector<int>& fvcoord,const vector<int>& ftcoord, const vector<int>& fncoord)
{
	Model_storage::pushFcoord(fvcoord,fncoord,ftcoord);

	++this->inter_info.to_fv_coord_index;
	++this->inter_info.to_fn_coord_index;
	++this->inter_info.to_ft_coord_index;
}

void ModelGroupStorage::get_groups(vector<Group> & dst_groups)
{
	for (Group_data::iterator it=this->groups.begin(); it!=this->groups.end(); ++it)
	{
		if (!it->group_info.finished) //neuzavrene skupiny uzavru (mela by to byt jen ta posledni vzdy pokud nebyl zavolan finish_group()!!!)
		{
			Group group=*it;

			group.group_info.to_fn_coord_index=this->inter_info.to_fn_coord_index;
			group.group_info.to_ft_coord_index=this->inter_info.to_ft_coord_index;
			group.group_info.to_fv_coord_index=this->inter_info.to_fv_coord_index;

			group.group_info.to_v_coord_index=this->inter_info.to_v_coord_index;
			group.group_info.to_t_coord_index=this->inter_info.to_t_coord_index;
			group.group_info.to_n_coord_index=this->inter_info.to_n_coord_index;

			dst_groups.push_back(group);
		}
		else
		{
			dst_groups.push_back(*it);
		}
	}
}