#ifndef __KERN_USER_H
#define __KERN_USER_H

/************************* Cppcall numbers ***********************/ 
#define CC_CYC_MOT      0  // just before motion calculation 
#define CC_CYC_XMOT     1  // just after motion calculation 
#define CC_CYC_FORD     2  // just before force-displacement calculation 
#define CC_CYC_XFORD    3  // just after force-displacement calculation 
#define CC_BALL_CREATE  4  // when ball cteated 
#define CC_BALL_DEL     5  // when ball deleted 
#define CC_CONT_CREATE  6  // when contact created
#define CC_CONT_DEL     7  // when contact deleted 
#define CC_BOND_CREATE  8  // when contact bond created 
#define CC_BOND_DEL     9  // when contact bond deleted
#define CC_PB_CREATE   10  // when parallel bond created 
#define CC_PB_DEL      11  // when parallel bond deleted 
#define CC_CYC_TOP     12  // start of calculation cycle
#define CC_PIPE_ACTIVE 13  // contact-addr, active status        
#define CC_FCYC_TOP    14  // top of fluid calculation cycle     
#define CC_BUILD_PROGRESS 15  // model-building, pbrick  

#define MAX_CPPCALLS   50


class Command;
class Terminal;
class File;
class InputStack;
class UcppPlotItem;
class Ufile;

struct CppCalls {  
	char *cFname;
	int iCallnum;
	CppCalls(void);
	CppCalls(const char *cName, int iNum);
	void write(File &) const;
	void read(File &);
};


class User {
  private:
    unsigned long ulType;
    unsigned long ulSizcalls; 
    unsigned long ulNumcalls; 
    CppCalls **cpc;
  public:
    // Creators
    User(unsigned long ulTypeIn, bool bRegister=false);
    virtual ~User(void);  
    // Accessors
		// Users need to define for pure virtual functions in their derived classes 
    virtual const char *Name(void) const = 0;
    virtual unsigned long Version(void) const = 0;
    virtual const char **FunctionNames(void) const = 0;
    virtual const char **PlotFunctionNames(void) const = 0;   
    virtual const char **IntVariableNames(void) const = 0;
    virtual const char **DoubleVariableNames(void) const = 0;
    virtual const char **BoolVariableNames(void) const = 0;
    virtual int ReturnIntVariable(int iN) const = 0;
    virtual double ReturnDoubleVariable(int iN) const =0;
    virtual bool ReturnBoolVariable(int iN) const = 0;
    // Manipulators
		// Users need to define for pure virtual functions in their derived classes 
    virtual User *Clone(void) const = 0;
    virtual void Execute(int iN) = 0;
    virtual void ExecutePlot(int iN, UcppPlotItem *upi) = 0;  
    virtual void AcceptIntVariable(int iN, int iV) = 0;
    virtual void AcceptDoubleVariable(int iN, double dV) = 0;
    virtual void AcceptBoolVariable(int iN, bool bV) = 0;
    // Save & Restore 
		virtual void write(Ufile &fi) const = 0;                           
		virtual void read(Ufile &fi) = 0; 
		virtual void remap(void) = 0;
		
		// ----- listed functions are used in PFC kernel -----
    // Accessors
    unsigned long Type(void) const { return ulType; }
    const char *ReturnPlotFunctionName(int iN);     
    // Static function to access all User Codes
    static unsigned long NumUcodes(void);       
    static const User *GetUcode(unsigned long ulPos); 
    static const User *FindByType(unsigned long ulType_in);
		static const unsigned long TypeToIndex(unsigned long ulType_in); // return index+1, False when return zero 
		static void AllCppCall(int ccid);  
		static void writeAll(File &fi);
		static void readAll(File &fi);
		static void remapAll(void);    
		static void New(void); 

    static int ProcessCommand(Command &com,Terminal &term);       
    static int SetCommand(Command &com,InputStack &,Terminal &term);
		static int chk_cppcall(Command &com,Terminal &term); 
    static int PrintCommand(Command &com,InputStack &,Terminal &term);
    static bool GetIntVariable(const char *strName, int *pi);
    static bool GetDoubleVariable(const char *strName, double *pd);
    static bool GetBoolVariable(const char *strName, bool *pb);
    static User *GetFromPlotFunctionName(const char *ccFname, int &indx);
	
};
extern User **usrArray;     


#endif
