/*!
  \file
  \brief UserInfo for pmsm related objects
  \author Vaclav Smidl.

  -----------------------------------
  BDM++ - C++ library for Bayesian Decision Making under Uncertainty

  Using IT++ for numerical operations
  -----------------------------------
*/

#include "pmsmDS.h"
#include <uibuilder.h>

class UIpmsmIM: public UIbuilder {
	protected:
	static void tmp_set ( Setting &S, IMpmsm* IM ) {
		//set_parameters( Rs0, Ls0, dt0, Ypm0, kp0, p0, J0, Mz0 )
		IM->set_parameters ( S["Rs"], S["Ls"], 125e-6, S["Fmag"], S["kp"],  S["p"], \
				S["J"], 0.0 );
	};
	public:
	UIpmsmIM():UIbuilder("pmsmIM"){};
	bdmroot* build ( Setting &S ) const {
		IMpmsm* tmp;
		//Switch to variants
		if (S.exists("variant")){
			string var=S["variant"];
			if (var=="Stat"){tmp=new IMpmsmStat;}
			if (var=="2o"){tmp=new IMpmsm2o;}
			if (var=="Mz"){tmp=new IMpmsmMz;}
			if (var=="StatMz"){tmp=new IMpmsmStatMz;}
		} else {
			tmp= new IMpmsm;
		}
		//Set parameters (recursively)
		UIcall<IMpmsm*> ( S["params"], &tmp_set , tmp );
		return tmp;
	}	
};
UIREGISTER ( UIpmsmIM );

//! UI for pmsm observation model
class UIpmsmOM: public UIbuilder {
	public:
		UIpmsmOM():UIbuilder("pmsmOM"){};
		bdmroot* build ( Setting &S ) const {
			return new OMpmsm;
		}	
};
UIREGISTER ( UIpmsmOM );


class UIpmsmOM4: public UIbuilder {
	public:
		UIpmsmOM4():UIbuilder("pmsmOM4"){};
		bdmroot* build ( Setting &S ) const {
			return new OMpmsm4;
		}	
};
UIREGISTER ( UIpmsmOM4 );


//!UI for pmsmDS, 
class UIpmsmDS: public UIbuilder {
	static void tmp_set ( Setting &S, pmsmDS* DS ) {
		//pmsmsim_set_parameters (( Rs0,  Ls0, Fmag0, Bf0, p0, kp0,  J0, Uc0, DT0,  dt0);
		DS->set_parameters ( S["Rs"], S["Ls"], S["Fmag"], S["Bf"], S["p"], S["kp"], \
		                     S["J"], S["Uc"], S["DT"], 1.0e-6 );
	};
public:
	UIpmsmDS() :UIbuilder ( "pmsmDS" ) {};
	bdmroot* build ( Setting &S ) const {
		pmsmDS* tmp = new pmsmDS ( );
		//Calling function tmp->tmp_set
		UIcall<pmsmDS*> ( S["params"], &tmp_set , tmp );
		
		// Default values of profiles for omega and Mz
		vec profW=vec("1.0");
		vec profM=vec("0.0");
		double tstep=1.0;
		
		if ( S.exists ( "tstep" ) ) {tstep=S["tstep"];}
		if ( S.exists ( "profileW" ) ) {profW=getvec ( S["profileW"] ) ;}
		if ( S.exists ( "profileM" ) ) {profM=getvec ( S["profileM"] ) ;}
		
		tmp->set_profile (tstep , profW, profM);
		
		string opts="";
		if ( S.exists ( "options" ) ) {opts=(const char*)S["options"];}
		tmp->set_options(opts);
		
		return tmp;
	};

};
UIREGISTER ( UIpmsmDS );

class UIpmsmCRB: public UIbuilder {
	public:
		UIpmsmCRB():UIbuilder("pmsmCRB"){};
		bdmroot* build ( Setting &S ) const {
			diffbifn* IM; UIbuild(S["IM"],IM);
			diffbifn* OM; UIbuild(S["OM"],OM);
		
		//parameters
			pmsmCRB* E; E=new pmsmCRB;
		
		//statistics
			int dim=IM->dimension();
			vec mu0;
			mat P0;
			if (S.exists("mu0")){mu0=getvec(S["mu0"]);}else{mu0=zeros(dim);};
			if (S.exists("P0")){mu0=getmat(S["P0"],dim);}else{P0=eye(dim);};
			E->set_statistics(mu0,P0);
		
			E->set_parameters(IM, OM, diag(getvec(S["dQ"])), diag(getvec(S["dR"])));

		//connect
			RV* drv; UIbuild(S["drv"],drv);
			E->set_drv(*drv);
			RV* rv; UIbuild(S["rv"],rv);
			E->set_rv(*rv);
			return E;
		}	
};
UIREGISTER ( UIpmsmCRB );

class UIpmsmCRBMz: public UIbuilder {
	public:
		UIpmsmCRBMz():UIbuilder("pmsmCRBMz"){};
		bdmroot* build ( Setting &S ) const {
			diffbifn* IM; UIbuild(S["IM"],IM);
			diffbifn* OM; UIbuild(S["OM"],OM);
		
		//parameters
			pmsmCRBMz* E; E=new pmsmCRBMz;
		
		//statistics
			int dim=IM->dimension();
			vec mu0;
			mat P0;
			if (S.exists("mu0")){mu0=getvec(S["mu0"]);}else{mu0=zeros(dim);};
			if (S.exists("dP0")){P0=diag(getvec(S["dP0"]));}else{
				if (S.exists("P0")){mu0=getmat(S["P0"],dim);}else{P0=eye(dim);};
			}
			E->set_statistics(mu0,P0);
		
			E->set_parameters(IM, OM, diag(getvec(S["dQ"])), diag(getvec(S["dR"])));

		//connect
			RV* drv; UIbuild(S["drv"],drv);
			E->set_drv(*drv);
			RV* rv; UIbuild(S["rv"],rv);
			E->set_rv(*rv);
			return E;
		}	
};
UIREGISTER ( UIpmsmCRBMz );
