#ifndef __PFCK_UDATA_H
#define __PFCK_UDATA_H

#ifndef __PFCK_UDVECT_H
#include "udvect.h"
#endif
#ifndef __PFCK_USTRING_H
#include "ustring.h"
#endif

enum NoticeId { N_color,	N_rad,		N_dens,
								N_prop,		N_vel,		N_disp,
								N_xfix,   N_yfix,   N_zfix,
#if DIM == 2
								N_rfix,
#elif DIM == 3
								N_rxfix,  N_ryfix,  N_rzfix,
#endif
                N_nstrength, N_sstrength,    
								N_default };

class Uball;
class Uwall;
class Ucontact;
class Ucirc;
struct Uparam;
class Ugobj;
class Ubond;
class Uclump;
#if DIM == 2
class Uwallseg;
#elif DIM == 3
class Uface;
#endif
class UcppPlotItem;
class Ufile; 
class Uobj;
class Ucell;        

class Udata {
	private:
		static NoticeId nID;
		static void *vp;

  public:
    Udata(void) { }
    ~Udata(void) { }

    static void Notice(void);				 // notify the change to PFC

		// ========== PFC Command function =============
		static void Ucommand(const char *ccCom);
		static void Ucommand(Ustring &uSt);
    static Ustring ToString(int &iV);
    static Ustring ToString(double &dV);

    static int UparamToInt(Uparam &p);
    static double UparamToDouble(Uparam &p);
    static void *UparamToPoint(Uparam &p);
    static const char *UparamToCChar(Uparam &p);
    static void IntToUparam(int &i, Uparam &p);
    static void DoubleToUparam(double &d, Uparam &p);
		static void PointToUparam(void *vp, Uparam &p);
    static Uparam &Fish(const char *ccName);
		
		// File I/O		
		static void Uwrite(Ufile &fi, const bool &b);            
		static void Uwrite(Ufile &fi, const char &c);            
		static void Uwrite(Ufile &fi, const int &i);             
		static void Uwrite(Ufile &fi, const long &l);            
		static void Uwrite(Ufile &fi, const short &s);           
		static void Uwrite(Ufile &fi, const unsigned char &uc);  
		static void Uwrite(Ufile &fi, const unsigned int &ui);   
		static void Uwrite(Ufile &fi, const unsigned long &ul);  
		static void Uwrite(Ufile &fi, const unsigned short &us); 
		static void Uwrite(Ufile &fi, const float &f);           
		static void Uwrite(Ufile &fi, const double &d);          
		static void Uwrite(Ufile &fi, const Udvect &udv);        
		static void Uwrite(Ufile &fi, const Uball *ubp);         
    static void Uwrite(Ufile &fi, const Uwall *uwp);
    static void Uwrite(Ufile &fi, const Ucontact *ucp);
    static void Uwrite(Ufile &fi, const Uclump *uclp); 
    static void Uwrite(Ufile &fi, const Uobj *uop);

		static void Uread(Ufile &fi, bool &b);                   
		static void Uread(Ufile &fi, char &c);                   
		static void Uread(Ufile &fi, int &i);                    
		static void Uread(Ufile &fi, long &l);                   
		static void Uread(Ufile &fi, short &s);                  
		static void Uread(Ufile &fi, unsigned char &uc);         
		static void Uread(Ufile &fi, unsigned int &ui);          
		static void Uread(Ufile &fi, unsigned long &ul);         
		static void Uread(Ufile &fi, unsigned short &us);        
		static void Uread(Ufile &fi, float &f);                  
		static void Uread(Ufile &fi, double &d);                 
		static void Uread(Ufile &fi, Udvect &udv);
    static Uball *Uread(Ufile &fi, Uball *ubp);                
    static Uwall *Uread(Ufile &fi, Uwall *uwp);  
    static Ucontact *Uread(Ufile &fi, Ucontact *ucp);
    static Uclump *Uread(Ufile &fi, Uclump *uclp); 
    static Uobj *Uread(Ufile &fi, Uobj *uop);
		static Uobj *Uremap(Uobj *uop);

		// ========== Intrinsic function =============
    // ---------- Mathematical function ----------
		static double degrad(double dDeg);
		static double grand(void);
		static const double pi(void);
		static double urand(void);
    // ---------- Utility function ----------
		static const double alpha_version(void);
		static const double beta_version(void);
		static int clock(void);
		static const int dim(void);
		static void error(const char *ccErr);
		static Uparam &cc_arg(const int iId);
		static void out(const char *ccStr);
		static const double rel_version(void);
		static const double version(void);
		static const int os(void);
		static int beep(int fq, int dur);
    // ---------- Plotting functions ----------
    static int draw_circle(Udvect &dvP, double rad, UcppPlotItem *upi);
    static int draw_line(Udvect &dvP1, Udvect &dvP2, UcppPlotItem *upi);
    static int draw_poly(Udvect *dvP, int iNpnt, bool bClose, UcppPlotItem *upi);
    static int draw_string(Udvect &dvP, const char *ccStr, UcppPlotItem *upi);
    static int fill_circle(Udvect &dvP, double rad, UcppPlotItem *upi);
    static int fill_poly(Udvect *dvP, int iNpnt, UcppPlotItem *upi);
    static int line_to(Udvect &dvP, UcppPlotItem *upi);
    static int move_to(Udvect &dvP, UcppPlotItem *upi);
    static int set_color(int iCindex, UcppPlotItem *upi);
    static int set_dash_pattern(int iPattern, UcppPlotItem *upi);
    static int set_font(double dMfactor, UcppPlotItem *upi);
    static int set_line_width(int iWidth, UcppPlotItem *upi);
#if DIM == 2
    static int draw_rect(Udvect &dvP1, Udvect &dvP2, UcppPlotItem *upi);
    static int fill_rect(Udvect &dvP1, Udvect &dvP2, UcppPlotItem *upi);
#endif
		// ========== PFC specific function =============
    // ---------- General funtion ----------
		static Uball *ball_head(void);														// 1000
    static Ucirc *circ_head(void);														// 1003
		static Uclump *clump_head(void);													// 1030   
    static Ucontact *contact_head(void);											// 1002
    static Uwall *wall_head(void);														// 1001
    static Uobj *uobj_head(void);                             // new
		static Uball *ball_near(Udvect &dvP);											// new
		static Uball *find_ball(unsigned long ulId);							// 1032
		static Ucirc *find_meas(unsigned long ulId);							// 1034
		static Uwall *find_wall(unsigned long ulId);							// 1033
		static const int pointer_type(void *p);                   // 
		static const double &av_cforce(void);											// 1038
		static const double &av_unbal(void);											// 1028
		static const unsigned long &ccount(void);									// 1009
		static const unsigned long &cycle(void);									// 1007
		static const double &e_body(void);												// 1025
		static const double &e_bond(void);												// 1024
		static const double &e_bound(void);												// 1026
		static const double &e_friction(void);										// 1022
		static const double &e_kinetic(void);											// 1021
		static const double &e_strain(void);											// 1023
		static double &given_tdel(void);													// 1016
//
		static Udvect &grav(void);																// 1013
		static double &local_damp(void);													// 1019
		static const unsigned long &max_bid(void);								// 1004
		static const double &max_cforce(void);										// 1039
		static const unsigned long &max_cid(void);								// 1006
		static const unsigned long &max_clid(void);								// 1031
		static const unsigned long &max_gwid(void);
		static const double &max_unbal(void);											// 1029
		static const unsigned long &max_wid(void);								// 1005
		static void pre_cycle(void);															// 1027
		static double &safety_fac(void);													// 1018
		static const unsigned long &step(void);										// 1008
		static const double &tdel(void);													// 1015
		static const double &time(void);													// 1014
//
//    static Ucirc *maddr(unsigned long ulId);								// 1020
//		static const double par_part(void);											// 1037

    // ---------- Uball funtion ----------
		static Ucontact *b_clist(Uball *ubp);											// 2001
		static void b_delete(Uball *ubp);											  	// 2076
		static Uparam &b_extra(Uball *ubp, int iN);								// 2066
    static const int &b_id(Uball *ubp);												// 2012
		static Uball *b_next(Uball *ubp);													// 2000
    static Uball *b_cllist(Uball *ubp);												// 2064
    static Uclump *b_clump(Uball *ubp);												// 2063  
    static const int b_shared(Uball *ubp);										// 2058
//
    static int &b_color(Uball *ubp);													// 2053 (notice)
		static const int &b_ctype(Uball *ubp);										// 2003
    static double &b_damp(Uball *ubp);												// 2061
    static double &b_dens(Uball *ubp);												// 2045 (notice)
    static double &b_fric(Uball *ubp);												// 2050 (notice)
    static double &b_kn(Uball *ubp);													// 2046 (notice)
    static double &b_ks(Uball *ubp);													// 2047 (notice)
    static const double &b_mass(Uball *ubp);									// 2042
    static const double &b_moi(Uball *ubp);										// 2044
		static double &b_rad(Uball *ubp);													// 2041 (notice)
    static const double &b_realmass(Uball *ubp);							// 2043
    static const double &b_realmoi(Uball *ubp);								// 2062
    static double &b_poiss(Uball *ubp);												// 2049
		static double &b_shearmod(Uball *ubp);										// 2048
//
    static bool &b_vfix(Uball *ubp, int dof);									// 2007
#if DIM == 2
		static bool &b_rfix(Uball *ubp);													// 2011
#elif DIM == 3
		static bool &b_rfix(Uball *ubp,int dof);									// 2071
#endif
		static Udvect &b_fap(Uball *ubp);													// 2036
#if DIM == 2
    static double &b_map(Uball *ubp);													// 2057
#elif DIM == 3
		static Udvect &b_map(Uball *ubp);													// 2070
#endif
//
		static const Udvect &b_pos(Uball *ubp);    								// 2016
		static Udvect &b_disp(Uball *ubp);												// 2075 (notice)
		static Udvect &b_vel(Uball *ubp);													// 2024 (notice)
#if DIM == 2
		static double &b_rvel(Uball *ubp);			 									// 2028
		static const double &b_mom(Uball *ubp);										// 2040
#elif DIM == 3
		static Udvect &b_rvel(Uball *ubp);			 									// 2068
		static const Udvect &b_mom(Uball *ubp);										// 2069
#endif
		static const Udvect &b_fob(Uball *ubp);										// 2032
		static void b_stress(Uball *ubp, double dAr[DIM][DIM]);		// 2067
#if DIM == 2
    static double &b_rot(Uball *ubp);													// 2060
#endif
//    static Udvect &b_u(Uball *ubp);													// 2020 mod
//		static Uparam &b_ex(Uball *ubp);												// 2051
//    static void del_ball(Uball *ubp);												// 2052
//    static const int b_type(Uball *ubp);										// 2059
    // ---------- Uwall funtion ----------
		static Ucontact *w_clist(Uwall *uwp);											// 8001
		static void w_delete(Uwall *uwp);													// 8068
		static Uparam &w_extra(Uwall *uwp, int iN);								// 8066
		static const int &w_id(Uwall *uwp);												// 8012
		static Uwall *w_next(Uwall *uwp);													// 8000
#if DIM == 2
		static Uwallseg *w_wlist(Uwall *uwp);											// 8065
#elif DIM == 3
		static Uface *w_flist(Uwall *uwp);												// 8064
#endif
		static int &w_color(Uwall *uwp);													// 8053 (notice)
		static double &w_fric(Uwall *uwp);												// 8050 (notice)
		static double &w_kn(Uwall *uwp);													// 8046 (notice)
		static double &w_ks(Uwall *uwp);													// 8047 (notice)
		static const Udvect &w_pos(Uwall *uwp);										// 8016
		static Udvect &w_vel(Uwall *uwp);													// 8024 (notice)
#if DIM == 2
		static double &w_rvel(Uwall *uwp);												// 8028
		static const double &w_mom(Uwall *uwp);										// 8077
#elif DIM == 3
		static Udvect &w_rvel(Uwall *uwp);									      // 8073
		static const Udvect &w_mom(Uwall *uwp);										// 8078
#endif
		static const Udvect &w_fob(Uwall *uwp);										// 8032
    static const int w_type(Uwall *uwp);                      // 1:stand,2:genwall,0:otherwise 
//		static Udvect &w_u(Uwall *uwp);													// 8020
//		static Uparam &w_ex(Uwall *uwp);													// 8051
//		static void del_wall(Uwall *uwp);													// 8052
//#if DIM == 2
//		static bool &w_fix(Uwall *uwp);														// 8067
//#endif

#if DIM == 2
    // ---------- Uwallseg funtion ----------  
//    static Uwallseg *ws_next(Uwallseg *uwsp);								  // 7000
//    static Uwallseg *ws_prev(Uwallseg *uwsp);									// 7001
		static const Udvect &ws_pos(Uwallseg *uwsp);							// new
		static Udvect &ws_vel(Uwallseg *uwsp);										// new
		static const Udvect &ws_un(Uwallseg *uws);								// new
		static const double &ws_length(Uwallseg *uws);						// 7008
		static Udvect &ws_u(Uwallseg *uwsp);											// new
#elif DIM == 3 
    // ---------- Uface funtion ----------  
		static const int &wf_id(Uface *ufp);											// 7101
//    static Uface *wf_next(Uface *ufp);											  // 7100
		static const Udvect &wf_un(Uface *ufp);										// new
#endif

		// ---------- Ucontact funtion ----------  
		static Ugobj *c_gobj1(Ucontact *ucp);											// new = 3001
		static Ugobj *c_gobj2(Ucontact *ucp);											// new = 3002
		static Ucontact *c_go1clist(Ucontact *ucp);								// new = 3003
		static Ucontact *c_go2clist(Ucontact *ucp);								// new = 3004
		static Uparam &c_extra(Ucontact *ucp, int iN);						// 3036  
		static bool &c_inhibit(Ucontact *ucp);										// 3033
		static int &c_jset(Ucontact *ucp);												// 3031
    static Ucontact *c_next(Ucontact *ucp);									  // 3000
		static Ubond *c_pb(Ucontact *ucp);												// 3026 
#if DIM == 2 
		static Uwallseg *c_wseg(Ucontact *ucp);										// 3005
#endif
    //		
		static const bool &c_bflag(Ucontact *ucp);								// 3007
		static const bool &c_broken(Ucontact *ucp);								// 3008
		static const double &c_fric(Ucontact *ucp);								// 3022
		static const double &c_hn(Ucontact *ucp);									// 3020 
		static const double &c_hs(Ucontact *ucp);									// 3021
		static const double &c_kn(Ucontact *ucp); 								// 3018
		static const double &c_ks(Ucontact *ucp);									// 3019
		static double &c_nstrength(Ucontact *ucp);								// 3023 (notice)
		static double &c_sstrength(Ucontact *ucp);								// 3024 (notice)
		static const int &c_type(Ucontact *ucp);									// 3006
		static void c_model(Ucontact *ucp, const char *cchName);  // 3035
		static const char *c_modelname(Ucontact *ucp);						// 3035
    static double c_prop(Ucontact *ucp, const char *cchName);  // 3034
    static void c_prop(Ucontact *ucp, const char *cchName, double dd); // 3034
		static Ubond *c_installpb(Ucontact *ucp);                 //
   //
		static const Udvect &c_pos(Ucontact *ucp);								// 3012
		static const Udvect &c_un(Ucontact *ucp);									// 3030
		static double &c_nforce(Ucontact *ucp);										// 3013
#if DIM == 2
		static double &c_sforce(Ucontact *ucp);										// 3017
#elif DIM == 3
		static Udvect &c_sforce(Ucontact *ucp);										// 3037
#endif
		static const double &c_slipwork(Ucontact *ucp);						// 3032
		static double &c_dampn(Ucontact *ucp);										// 3038
		static double &c_damps(Ucontact *ucp);										// 3039
//		static Uparam &c_ex(Ucontact *ucp);												// 3025

    // ---------- Ubond funtion ----------  
		static double &pb_kn(Ubond *upbp);												// 5001
		static double &pb_ks(Ubond *upbp);												// 5002
		static double &pb_nstrength(Ubond *upbp);									// 5003
		static double &pb_sstrength(Ubond *upbp);									// 5004
		static double &pb_rad(Ubond *upbp);												// 5000
//
		static double &pb_nforce(Ubond *upbp);										// 5007
#if DIM == 2
		static double &pb_sforce(Ubond *upbp);										// 5011
		static double &pb_mom(Ubond *upbp);												// 5016
#elif DIM == 3
		static Udvect &pb_sforce(Ubond *upbp);										// 5017
		static Udvect &pb_mom(Ubond *upbp);												// 5018
		static double &pb_tmom(Ubond *upbp);											// 5012
		static Udvect &pb_bmom(Ubond *upbp);			
#endif
		static double &pb_nstress(Ubond *upbp);										// 5005
		static double &pb_sstress(Ubond *upbp);										// 5006
    
		// ---------- Ucirc funtion ----------  
//		enum MeasCodeId { M_stress,  M_strain };
		//
		static const unsigned long &m_id(Ucirc *ucip);						// 4027
    static Ucirc *m_next(Ucirc *ucip);											  // 4028
		static Udvect &m_pos(Ucirc *ucip);												// 4025
		static double &m_rad(Ucirc *ucip);												// 4026
//
		static const double &m_coord(Ucirc *ucip);								// 4001
		static const double &m_poros(Ucirc *ucip);								// 4002
		static const double &m_sfrac(Ucirc *ucip);								// 4003
		static void measure(Ucirc *ucip, int iCode);      				// 4000
		static const double &m_s11(Ucirc *ucip);									// 4004
		static const double &m_s12(Ucirc *ucip);									// 4005
		static const double &m_s21(Ucirc *ucip);									// 4006
		static const double &m_s22(Ucirc *ucip);									// 4007
#if DIM == 3
		static const double &m_s13(Ucirc *ucip);									// 4008
		static const double &m_s31(Ucirc *ucip);									// 4009
		static const double &m_s23(Ucirc *ucip);									// 4010
		static const double &m_s32(Ucirc *ucip);									// 4011
		static const double &m_s33(Ucirc *ucip);									// 4012
#endif
		static const double &m_ed11(Ucirc *ucip);									// 4013
		static const double &m_ed12(Ucirc *ucip);									// 4014
		static const double &m_ed21(Ucirc *ucip);									// 4015
		static const double &m_ed22(Ucirc *ucip);									// 4016
#if DIM == 3
		static const double &m_ed13(Ucirc *ucip);									// 4017
		static const double &m_ed31(Ucirc *ucip);									// 4018
		static const double &m_ed23(Ucirc *ucip);									// 4019
		static const double &m_ed32(Ucirc *ucip);									// 4020
		static const double &m_ed33(Ucirc *ucip);									// 4021
#endif

    // ---------- Uclump  funtion ----------  
		static Uclump *cl_add(Uclump  *uclp, Uball *ubp);					// 6000
		static Uparam &cl_extra(Uclump  *uclp, int iN);						// 6013  
    static Uball  *cl_list(Uclump  *uclp);										// 6004
		static const unsigned long &cl_id(Uclump  *uclp);					// 6002
    static Uclump  *cl_next(Uclump  *uclp);									  // 6003
		static void cl_rel(Uclump  *uclp, Uball *ubp);						// 6001
//
		static const Udvect &cl_pos(Uclump  *uclp);						  	// 6014
		static Udvect &cl_vel(Uclump  *uclp);											// 6018
#if DIM == 2
		static double &cl_rvel(Uclump  *uclp);										// 6022
//		static const double &cl_mom(Uclump  *uclp);							// 6024
#elif DIM == 3
		static Udvect &cl_rvel(Uclump  *uclp);										// 6023
//		static const Udvect &cl_mom(Uclump  *uclp);							// 6028
#endif
		static const Udvect &cl_fob(Uclump  *uclp);								// 6012

    // ---------- Uobj  funtion ----------  
    static Uobj *u_next(Uobj *uobp);                          // new
		static const unsigned long u_type(Uobj *uobj);            // new

    // ---------- Ucell funtion ----------  
		static const int cell_xnum(void);                         // new
		static const int cell_ynum(void);                         // new
		static const Udvect &cell_low(void);                      // new
		static const double cell_size(void);                      // new
#if DIM == 3
		static const int cell_znum(void);                         // new 
#endif
#if DIM == 2
    static Ucell *cell_list(int ix, int iy);                  // new (1-cell_xnum)
																													    //     (1-cell_ynum)
#elif DIM == 3
    static Ucell *cell_list(int ix, int iy, int z);           // new (1-cell_ynum)
#endif
    static Ucell *cell_next(Ucell *uclp);                     // new
    static Ugobj *cell_object(Ucell *uclp);                   // new

    // ---------- Ufcell funtion ----------  
		static const double &fc_x(int i, int j, int k=0);					// new
		static const double &fc_y(int i, int j, int k=0);					// new
#if DIM == 3
		static const double &fc_z(int i, int j, int k);						// new
#endif
		static const double &fc_xvel(int i, int j, int k=0);			// new
		static const double &fc_yvel(int i, int j, int k=0);			// new
#if DIM == 3
		static const double &fc_zvel(int i, int j, int k);				// new
#endif
		static const double &fc_pre(int i, int j, int k=0);				// new
		static double &fc_por(int i, int j, int k=0);							// new
		static double &fc_xfap(int i, int j, int k=0);						// new
		static double &fc_yfap(int i, int j, int k=0);						// new
#if DIM == 3
		static double &fc_zfap(int i, int j, int k);							// new
#endif
		static double &fc_bxvel(int i, int j, int k=0);						// new
		static double &fc_byvel(int i, int j, int k=0);						// new
#if DIM == 3
		static double &fc_bzvel(int i, int j, int k);							// new
#endif

};




#endif