/*!\file ControlInput2.c
 * \brief: implementation of the ControlInput2 object
 */

#ifdef HAVE_CONFIG_H
	#include <config.h>
#else
#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
#endif

#include "./ControlInput2.h"
#include "./ElementInput2.h"
#include "./TriaInput2.h"
#include "./PentaInput2.h"
//#include "../../toolkits/objects/Vector.h"

/*ControlInput2 constructors and destructor*/
ControlInput2::ControlInput2(){/*{{{*/
	control_id  = 0;
	values      = NULL;
	savedvalues = NULL;
	minvalues   = NULL;
	maxvalues   = NULL;
	gradient    = NULL;
}
/*}}}*/
ControlInput2::ControlInput2(int nbe, int nbv,int input_layout_enum,int interp,int id){/*{{{*/

	this->control_id  = id;
	this->layout_enum = input_layout_enum;

	_assert_(interp==P1Enum);

	switch(this->layout_enum){
		case TriaInput2Enum:
			this->values     =new TriaInput2(nbe,nbv,interp);
			this->savedvalues=new TriaInput2(nbe,nbv,interp);
			this->minvalues  =new TriaInput2(nbe,nbv,interp);
			this->maxvalues  =new TriaInput2(nbe,nbv,interp);
			this->gradient   =new TriaInput2(nbe,nbv,interp);
			break;
		case PentaInput2Enum:
			this->values     =new PentaInput2(nbe,nbv,interp);
			this->savedvalues=new PentaInput2(nbe,nbv,interp);
			this->minvalues  =new PentaInput2(nbe,nbv,interp);
			this->maxvalues  =new PentaInput2(nbe,nbv,interp);
			this->gradient   =new PentaInput2(nbe,nbv,interp);
			break;
		default:
			_error_("Input of Enum \"" << EnumToStringx(input_layout_enum) << "\" not supported yet by ControlInput2");
	}
}
/*}}}*/
ControlInput2::~ControlInput2(){/*{{{*/
	if(values)      delete values;
	if(savedvalues) delete savedvalues;
	if(minvalues)   delete minvalues;
	if(maxvalues)   delete maxvalues;
	if(gradient)    delete gradient;
}
/*}}}*/

/*Object virtual functions definitions:*/
Input2* ControlInput2::copy() {/*{{{*/

	ControlInput2* output=NULL;

	output = new ControlInput2();
	output->enum_type=this->enum_type;
	output->control_id=this->control_id;
	output->layout_enum = this->control_id;

	if(values)      output->values      = xDynamicCast<ElementInput2*>(this->values->copy());
	if(savedvalues) output->savedvalues = xDynamicCast<ElementInput2*>(this->savedvalues->copy());
	if(minvalues)   output->minvalues   = xDynamicCast<ElementInput2*>(this->minvalues->copy());
	if(maxvalues)   output->maxvalues   = xDynamicCast<ElementInput2*>(this->maxvalues->copy());
	if(gradient)    output->gradient    = xDynamicCast<ElementInput2*>(this->gradient->copy());

	return output;
}
/*}}}*/
void ControlInput2::DeepEcho(void){/*{{{*/

	_printf_("ControlInput2:\n");
	_printf_(setw(15)<<"   ControlInput2 "<<setw(25)<<left<<EnumToStringx(this->enum_type)<<"\n");
	_printf_(setw(15)<<"   ControlInput2 "<<setw(25)<<left<<EnumToStringx(this->layout_enum)<<"\n");
	_printf_("---values: \n");     if (values)      values->Echo();
	_printf_("---savedvalues: \n");if (savedvalues) savedvalues->Echo();
	_printf_("---minvalues: \n");  if (minvalues)   minvalues->Echo();
	_printf_("---maxvalues: \n");  if (maxvalues)   maxvalues->Echo();
	_printf_("---gradient: \n");   if (gradient){    gradient->Echo();} else{_printf_("     Not set yet\n");}
}
/*}}}*/
void ControlInput2::Echo(void){/*{{{*/
	this->DeepEcho();
}
/*}}}*/
int  ControlInput2::Id(void){ return -1; }/*{{{*/
/*}}}*/
void ControlInput2::Marshall(char** pmarshalled_data,int* pmarshalled_data_size, int marshall_direction){ /*{{{*/

	MARSHALLING_ENUM(ControlInput2Enum);
	_error_("Not implemented");
}
/*}}}*/
int  ControlInput2::ObjectEnum(void){/*{{{*/

	return ControlInput2Enum;

}
/*}}}*/

void ControlInput2::SetControl(int interp,int numindices,int* indices,IssmDouble* values_in,IssmDouble* values_min,IssmDouble* values_max){/*{{{*/

	_assert_(this);

	/*Set input*/
	//TriaInput2* input = xDynamicCast<TriaInput2*>(this->inputs[id]);
	this->values->SetInput(interp,numindices,indices,values_in);
	this->minvalues->SetInput(interp,numindices,indices,values_min);
	this->maxvalues->SetInput(interp,numindices,indices,values_max);
}
/*}}}*/
void ControlInput2::SetGradient(int interp,int numindices,int* indices,IssmDouble* values_in){/*{{{*/

	_assert_(this);
	_assert_(this->gradient);
	this->gradient->SetInput(interp,numindices,indices,values_in);
}
/*}}}*/
void ControlInput2::SetGradient(int interp,int numindices,int* indices,IssmDouble* values_in,int n){/*{{{*/

	if(this->values->ObjectEnum()!=TransientInput2Enum)_error_("you are in the wrong place, go home");
	_assert_(this);
	_assert_(this->gradient);
	_error_("S");

	//TransientInput2* transient_input = xDynamicCast<TransientInput2*>(this->gradient);
	//TransientInput2* values_input    = xDynamicCast<TransientInput2*>(this->values);
	//if(values_input->numtimesteps==transient_input->numtimesteps){
	//	TransientInput* new_trans_input = new TransientInput2(ControlInputGradEnum);
	//	IssmDouble time = transient_input->GetTimeByOffset(timestep);
	//	for(int i=0;i<transient_input->numtimesteps;i++){
	//		if(transient_input->timesteps[i]==time) new_trans_input->AddTimeInput(xDynamicCast<TriaInput*>(gradient_in),time);
	//		else {
	//			Input2* input = transient_input->GetTimeInput(transient_input->timesteps[i]);
	//			new_trans_input->AddTimeInput(xDynamicCast<TriaInput2*>(input),transient_input->timesteps[i]);
	//		}
	//	}
	//	this->gradient=new_trans_input;
	//}
	//else{
	//	IssmDouble time = values_input->GetTimeByOffset(timestep);
	//	transient_input->AddTimeInput(gradient_in,time);
	//}


	//NEW??
	//this->gradient->SetInput(interp,numindices,indices,values_in);
}
/*}}}*/
TriaInput2* ControlInput2::GetTriaInput(){/*{{{*/

	/*Cast and return*/
	if(this->values->ObjectEnum()!=TriaInput2Enum){
		_error_("Cannot return a TriaInput2");
	}
	return xDynamicCast<TriaInput2*>(this->values);

}
/*}}}*/
PentaInput2* ControlInput2::GetPentaInput(){/*{{{*/

	/*Cast and return*/
	if(this->values->ObjectEnum()!=PentaInput2Enum){
		_error_("Cannot return a PentaInput2");
	}
	return xDynamicCast<PentaInput2*>(this->values);

}
/*}}}*/
ElementInput2* ControlInput2::GetInput2(const char* data){/*{{{*/

	if(strcmp(data,"value")==0){
		_assert_(values);
		return values;
	}
	else if(strcmp(data,"savedvalues")==0){
		_assert_(savedvalues);
		return values;
	}
	else if (strcmp(data,"lowerbound")==0){
		_assert_(minvalues);
		return minvalues;
	}
	else if (strcmp(data,"upperbound")==0){
		_assert_(maxvalues);
		return maxvalues;
	}
	else if (strcmp(data,"gradient")==0){
		_assert_(gradient);
		return gradient;
	}
	else{
		_error_("Data " << data << " not supported yet");
	}

}
/*}}}*/
