/*
 * UpdateElementsAndMaterialsControl:
 */

#include "../../../Container/Container.h"
#include "../../../toolkits/toolkits.h"
#include "../../../modules/modules.h"
#include "../../../io/io.h"
#include "../../../EnumDefinitions/EnumDefinitions.h"
#include "../../../classes/objects/objects.h"
#include "../../../shared/shared.h"
#include "../../MeshPartitionx/MeshPartitionx.h"
#include "../../../include/include.h"
#include "../ModelProcessorx.h"

void	UpdateElementsAndMaterialsControl(Elements* elements,Materials* materials, IoModel* iomodel){

	/*Intermediary*/
	int       i;
	int       counter;
	Element  *element = NULL;
	Material *material = NULL;
	int    numberofelements;
	int    num_control_type;
	bool   control_analysis;

	/*Fetch parameters: */
	iomodel->Constant(&numberofelements,MeshNumberofelementsEnum);
	iomodel->Constant(&control_analysis,InversionIscontrolEnum);
	if(control_analysis) iomodel->Constant(&num_control_type,InversionNumControlParametersEnum);

	/*Now, return if no control*/
	if (!control_analysis) return;

	/*Fetch data needed: */
	iomodel->FetchData(1,MeshElementsEnum);
	iomodel->FetchDataToInput(elements,InversionVxObsEnum);
	iomodel->FetchDataToInput(elements,InversionVyObsEnum); 
	iomodel->FetchDataToInput(elements,InversionThicknessObsEnum);

	iomodel->FetchData(4,InversionControlParametersEnum,InversionCostFunctionsCoefficientsEnum,InversionMinParametersEnum,InversionMaxParametersEnum);
	for(i=0;i<num_control_type;i++){
		switch(reCast<int,IssmDouble>(iomodel->Data(InversionControlParametersEnum)[i])){
			case BalancethicknessThickeningRateEnum: iomodel->FetchData(1,BalancethicknessThickeningRateEnum); break;
			case VxEnum:   iomodel->FetchData(1,VxEnum); break;
			case VyEnum:   iomodel->FetchData(1,VyEnum); break;
			case FrictionCoefficientEnum: iomodel->FetchData(1,FrictionCoefficientEnum); break;
			case MaterialsRheologyBbarEnum:    iomodel->FetchData(1,MaterialsRheologyBEnum); break;
			case MaterialsRheologyZbarEnum:    iomodel->FetchData(1,MaterialsRheologyZEnum); break;
			default: _error_("Control " << EnumToStringx(reCast<int,IssmDouble>(iomodel->Data(InversionControlParametersEnum)[i])) << " not implemented yet");
		}
	}

	/*Update elements and materials: */
	counter=0;
	for (i=0;i<numberofelements;i++){
		if(iomodel->my_elements[i]){
			element=(Element*)elements->GetObjectByOffset(counter);
			element->InputUpdateFromIoModel(i,iomodel); //we need i to index into elements.

			material=(Material*)materials->GetObjectByOffset(counter);
			material->InputUpdateFromIoModel(i,iomodel); //we need i to index into elements.
			counter++;
		}
	}

	/*Free data: */
	iomodel->DeleteData(1+4+6,MeshElementsEnum,InversionControlParametersEnum,InversionCostFunctionsCoefficientsEnum,InversionMinParametersEnum,InversionMaxParametersEnum,BalancethicknessThickeningRateEnum,VxEnum,VyEnum,FrictionCoefficientEnum,MaterialsRheologyBEnum,MaterialsRheologyZEnum);
}
