#include "bob_dom_frame.h"
//---------------------------------------------------------------------------------
bool bob_dom_frame::point3d::load(bob_dom_ibinaryfilestream& is)
{
	if(!is.good()) return false;
	is >> x >> y >> z;
	return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::point3d::toFile(bob_dom_otextfilestream & os)
{
	os << noSemicolons << x << ';' << y << ';' << z << "; ";
	return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::point3d::toFile(bob_dom_obinaryfilestream& os)
{
	os << x << y << z;
	return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::rgb::load(bob_dom_ibinaryfilestream& is)
{
	if(!is.good()) return false;
	is >> r >> g >> b;
	return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::rgb::toFile(bob_dom_otextfilestream & os)
{
	os << noSemicolons << r << ';' << g << ';' << b << "; ";
	return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::rgb::toFile(bob_dom_obinaryfilestream& os)
{
	os << r << g << b;
	return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::angle_axis::load(bob_dom_ibinaryfilestream& is)
{
	if(!is.good()) return false;
	is >> angle >> x >> y >> z;
	
	return(!is.fail());
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::angle_axis::toFile(bob_dom_otextfilestream& os)
{
	os << noSemicolons << angle << ';' << x << ';' << y << ';' << z << "; ";
	return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::angle_axis::toFile(bob_dom_obinaryfilestream& os)
{
	os << angle << x << y << z;
	return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::tcb_info::load(bob_dom_ibinaryfilestream& is)
{
	if(!is.good()) return false;
	is >> tension >> continuity >> bias >> easeFrom >> easeTo;
	return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::tcb_info::toFile(bob_dom_otextfilestream & os)
{
	os << noSemicolons;
	os << tension << ';' << continuity << ';' << bias << ';' << easeFrom << ';' << easeTo << "; ";
	return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::tcb_info::toFile(bob_dom_obinaryfilestream& os)
{
	os << tension << continuity << bias << easeFrom << easeTo;
	return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::load(bob_dom_ibinaryfilestream& is)
{
	is >> flags;
	
	// if we don't know some bits in the flags, the load will probably fail but not necessarily
	if((flags & ~flagMask) > 0)
		error(s_warning, e_unsupportedFrameFlags, "0x%X - unsupported bits set in frame flags", flags);
	
	// these flags are "known" but they were never found so I don't know how to treat them
	if(flags & CUT_F_POSBEZINFO)
		error(s_warning, e_unsupportedFrameFlags, "0x%X: CUT_F_POSBEZINFO encountered - don't know how to output", flags);
	if(flags & CUT_F_SAMESCALE)
		error(s_warning, e_unsupportedFrameFlags, "0x%X: CUT_F_SAMESCALE encountered", flags);
		
	if((flags & CUT_F_SAMEPOS)==0){
		if(position.load(is)==false) { error(e_notEnoughData, "Error loading position"); return false; }
		if((flags & CUT_F_POSTCBINFO) > 0) {
			pos_tcb_info=new tcb_info();
			if(pos_tcb_info->load(is)==false) { error(e_notEnoughData, "Error loading position TCB data"); return false; }
		}
	}
	if((flags & CUT_F_SAMEROT)==0 && (flags & CUT_F_ROT) > 0){
		rotation=new angle_axis();
		if(rotation->load(is)==false) { error(e_notEnoughData, "Error loading rotation"); return false; }
		if((flags & CUT_F_ROTTCBINFO) > 0) {
			rot_tcb_info=new tcb_info();
			if(rot_tcb_info->load(is)==false) { error(e_notEnoughData, "Error loading rotation TCB data"); return false; }
		}
	}
	if((flags & CUT_F_TARGETPOS) > 0) {
		if((flags & CUT_F_SAMETARGET) == 0){
			targetPos=new point3d();
			if(targetPos->load(is)==false) { error(e_notEnoughData, "Error loading target position data"); return false; }
		}
		if((flags & CUT_F_SAMEROT) == 0){
			is >> rollAngle;
			if(is.fail()) { error(e_notEnoughData, "Error loading roll angle"); return false; }
		}
		if((flags & CUT_F_TPOSTCBINFO) > 0) {
			tpos_tcb_info=new tcb_info();
			if(tpos_tcb_info->load(is)==false) { error(e_notEnoughData, "Error loading target position TCB data"); return false; }
		}
	}
	if((flags & CUT_F_SAMEFOV)==0 && (flags & CUT_F_FOV) > 0){
		is >> fov;
		if(is.fail()) { error(e_notEnoughData, "Error loading FOV"); return false; }
	}
	if((flags & CUT_F_SAMECOLOR)==0 && (flags & CUT_F_COLOR) > 0){
		color=new rgb();
		if(color->load(is)==false) { error(e_notEnoughData, "Error loading RGB"); return false; }
	}
	
	is >> length >> index;
	if(is.fail()) { error(e_notEnoughData, "Error loading length or index"); return false; }
	
	return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::toFile(bob_dom_obinaryfilestream& os)
{
	os << flags;
	
	if((flags & CUT_F_SAMEPOS)==0){
		position.toFile(os);
		if(pos_tcb_info)
			pos_tcb_info->toFile(os);
	}
	if((flags & CUT_F_SAMEROT)==0 && rotation){
		rotation->toFile(os);
		if(rot_tcb_info)
			rot_tcb_info->toFile(os);
	}
	if(flags & CUT_F_TARGETPOS) {
		if(targetPos)
			targetPos->toFile(os);
			
		if((flags & CUT_F_SAMEROT) == 0)
			os << rollAngle;
			
		if(tpos_tcb_info)
			tpos_tcb_info->toFile(os);
	}
	if((flags & CUT_F_SAMEFOV)==0 && (flags & CUT_F_FOV) > 0)
		os << fov;
		
	if((flags & CUT_F_SAMECOLOR)==0 && (flags & CUT_F_COLOR) > 0)
		color->toFile(os);
	
	os << length << index;
	return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_frame::toFile(bob_dom_otextfilestream& os)
{
	os << noSemicolons << "{ " << hex << "0x" << flags << dec << "; ";
	
	if((flags & CUT_F_SAMEPOS)==0){
		position.toFile(os);
		if(pos_tcb_info)
			pos_tcb_info->toFile(os);
	}
	if((flags & CUT_F_SAMEROT)==0 && rotation){
		rotation->toFile(os);
		if(rot_tcb_info)
			rot_tcb_info->toFile(os);
	}
	if((flags & CUT_F_TARGETPOS) > 0) {
		if(targetPos)
			targetPos->toFile(os);
			
		if((flags & CUT_F_SAMEROT) == 0)
			os << rollAngle << "; ";
			
		if(tpos_tcb_info)
			tpos_tcb_info->toFile(os);
	}
	if((flags & CUT_F_SAMEFOV)==0 && (flags & CUT_F_FOV) > 0)
		os << fov << "; ";
		
	if((flags & CUT_F_SAMECOLOR)==0 && (flags & CUT_F_COLOR) > 0)
		color->toFile(os);
	
	os << autoSemicolons << length << index << noSemicolons << '}';
	
	return os.good();
}
//---------------------------------------------------------------------------------
int bob_dom_frame::valueCount()
{
	int size=0;
	
	if((flags & CUT_F_SAMEPOS)==0){
		size+=3;
		if((flags & CUT_F_POSTCBINFO) > 0)
			size+=5;
	}
	if((flags & CUT_F_SAMEROT)==0 && (flags & CUT_F_ROT) > 0){
		size+=4;
		if((flags & CUT_F_ROTTCBINFO) > 0)
			size+=5;
	}
	if((flags & CUT_F_TARGETPOS) > 0) {
		if((flags & CUT_F_SAMETARGET) == 0)
			size+=3;
			
		if((flags & CUT_F_SAMEROT) == 0)
			size++;
			
		if((flags & CUT_F_TPOSTCBINFO) > 0)
			size+=5;
	}
	if((flags & CUT_F_SAMEFOV)==0 && (flags & CUT_F_FOV) > 0)
		size+=1;
	if((flags & CUT_F_SAMECOLOR)==0 && (flags & CUT_F_COLOR) > 0)
		size+=3;
	return size;
}
//---------------------------------------------------------------------------------