/*!\file:  SetStructureField.cpp
	usage:
	array=SetStructureField(array,name,field,value);
	
	where:

	input:

		array: structure array
		name: field name of structure array (ie: array.name)
		field: field of array.name structure
		value: value of array.name (ie: array.name.field=value;
		
	output:
		array: output structure array
*/
	

#include "./SetStructureField.h" 


void mexFunction( int nlhs, mxArray* plhs[],
				  int nrhs, const mxArray* prhs[])
{
	/*indexing: */
	int i,j,n;
	
	
	/*Output: */
	mxArray* output=NULL;

	/*Input: */
	int      array_size;
	char*    name          = NULL;
	char*    field         = NULL;
	char*    string        = NULL;

	double*  pvalue        = NULL;
	int      M,N;
	double*  valuen        = NULL;
	mxArray* pvaluen       = NULL;

	
	/*Matlab array manipulation: */
	mxArray*       element=NULL;
	mxArray* pfield        =NULL;

	/*Boot module: */
	MODULEBOOT();

	/*checks on arguments on the matlab side: */
	CheckNumMatlabArguments(nlhs,NLHS,nrhs,NRHS,__FUNCT__,&SetStructureFieldUsage);

	/*Fetch data: */
	array_size=mxGetM(ARRAYHANDLE);

	/*Duplicate input array, so that it can be returned as output. Matlab won't allow modifying an input mxArray!: */
	output=mxDuplicateArray(ARRAYHANDLE);

	/*Get name in array.name: */
	FetchData((void**)&name,NULL,NULL,NAMEHANDLE,"String",NULL);

	/*Get field in array.field: */
	FetchData((void**)&field,NULL,NULL,FIELDHANDLE,"String",NULL);

	/*Branch out on type of value: */
	if (mxIsChar(VALUEHANDLE)){

		/*Get string store in the value mxArray: */
		FetchData((void**)&string,NULL,NULL,VALUEHANDLE,"String",NULL);

		/*Start looping on output array: */
		for (n=0;n<array_size;n++){

			/*Get pointer to array(n).name: */
			element=mxGetField(output,n,name);

			/*Set array(n).name.field=value: */
			mxSetField(element,0,field,mxCreateString(string));
		}
	}
	else{

		/*Get value pointer: */
		pvalue=mxGetPr(VALUEHANDLE);
		M=mxGetM(VALUEHANDLE);
		N=mxGetN(VALUEHANDLE);
		
		if(M==1){

			/*Start looping on output array: */
			for (n=0;n<array_size;n++){

				/*Get pointer to array(n).name: */
				element=mxGetField(output,n,name);

				/*Set array(n).name.field=value: */
				mxSetField(element,0,field,mxCreateDoubleScalar(*pvalue));
			}
		}
		else{
			/*Value is a multidimensional array: */

			/*Start looping on output array: */
			for (n=0;n<array_size;n++){

				/*For level n, recover value(n,:): */
				valuen=(double*)xmalloc(N*sizeof(double));
				for(i=0;i<N;i++){
					valuen[i]=*(pvalue+M*i+n);
				}

				/*Set array(n).name.field=value(n,:): */
				pvaluen=mxCreateDoubleMatrix(N,1,mxREAL);
				mxSetPr(pvaluen,valuen);
			
				element=mxGetField(output,n,name);
				mxSetField(element,0,field,pvaluen);

			}
		}
	}
	
	/*Assign output array: */
	OUTPUTHANDLE=output;
	
	/*end module: */
	MODULEEND();
}

void SetStructureFieldUsage(void)
{
	printf("   SetStructureField.c\n");
	printf("   usage:\n");
	printf("   array=SetStructureField(array,name,field,value);\n");
	printf("   \n");
	printf("   where:\n");
	printf("   \n");
	printf("   input:\n");
	printf("   \n");
	printf("   	array: structure array\n");
	printf("   	name: field name of structure array (ie: array.name)\n");
	printf("   	field: field of array.name structure\n");
	printf("   	value: value of array.name (ie: array.name.field=value;\n");
	printf("   	\n");
	printf("    output:\n");
	printf("   	array: output structure array\n");
	printf("\n");
}
