/////////////////////////////////////////////////////////////////////////////
// internal.h
//
// SIMLIB version: 2.18
// Date: 2004-01-25
//
// Copyright (c) 1991-2004 Petr Peringer 
//
// This library is licensed under GNU Library GPL. See the file COPYING.
//

/*! \mainpage SIMLIB 
 *
 * SIMLIB/C++ is the SIMulation LIBrary for C++ programming language
 * 
 * \section intro Introduction
 *
 * This documentation is experimental for now.
 * It is made by program doxygen <B>without</B> any special formatting of
 * original source code.
 *
 *
 */

//
// SIMLIB internal declarations
// 

#ifndef __SIMLIB__INTERNAL_H__
#define __SIMLIB__INTERNAL_H__

// simlib.h should be included first

////////////////////////////////////////////////////////////////////////////
// debugging ...
//
//#define NDEBUG   // uncomment if you don't want to compile debug info

#ifdef NDEBUG
#   define dprintf(s)
#   define DEBUG(c,s)
#   define DEBUG_INFO 
#else
#   define DEBUG_INFO "/debug"
    extern unsigned long SIMLIB_debug_flag; // debugging flags
#   define dprintf(f) \
        do { if( SIMLIB_debug_flag ) \
                 { _Print("DEBUG: T=%-10g ", (double)Time); \
                   _Print f; _Print("\n"); \
        } }while(0)
#   define DEBUG(c,f) \
    do{ if( SIMLIB_debug_flag & (c) ) \
            { _Print("DEBUG: T=%-10g ", (double)Time); \
              _Print f; _Print("\n"); \
    } }while(0)
    // classification of DEBUG messages
#   define DBG_ALL         ~0L          // print all debugging info
#   define DBG_NEW         (1L)         // new/delete (memory allocation)
#   define DBG_CTR         (1L<<1)      // ctr/dtr (creation/destruction)
#   define DBG_INIT        (1L<<2)      // initialization
#   define DBG_CHG         (1L<<3)      // object changes
#   define DBG_STEP        (1L<<4)      // continuous step control
#   define DBG_CONTI       (1L<<5)      // continuous blocks
#   define DBG_FACSTO      (1L<<6)      // Enter,Leave,Seize,Release
#   define DBG_PROCESS     (1L<<7)      // Process
#   define DBG_QUEUE       (1L<<8)      // Queue operations
#   define DBG_CALENDAR    (1L<<9)      // Scheduling
#   define DBG_SIMULATOR   (1L<<10)     // Simulator actions - control
#   define DBG_BEXPR       (1L<<11)     // Block expressions
#   define DBG_WU          (1L<<12)     // WaitUntil
#   define DBG_NUMINT      (1L<<13)     // numerical integration methods
#   define DBG_THREAD      (1L<<14)     // Process-switching
#   define DBG_MODULE      (1L<<15)     // Module cleanup: id_string,...
#   define DBG_ATEXIT      (1L<<16)     // SIMLIB_atexit
#endif // NDEBUG

    
////////////////////////////////////////////////////////////////////////////
// module identification
// 
#define SIMLIB_IMPLEMENTATION                            \
   static int SIMLIB_module_num =                        \
      SIMLIB_module_id.Init(                             \
	"(" __FILE__                                     \
	", SIMLIB-" SIMLIB_VERSION  DEBUG_INFO           \
	", " SIMLIB_SYSTEM                               \
	"/" SIMLIB_COMPILER                              \
	", " __DATE__ " " __TIME__                       \
	")"                                              \
      );

// SIMLIB atexit function (for internal use only)
typedef void (*SIMLIB_atexit_function_t)();
void SIMLIB_atexit(SIMLIB_atexit_function_t p);

////////////////////////////////////////////////////////////////////////////
// error handling functions
//

#include "errors.h" // error messages (generated by program generr)

// print specific error messages
void SIMLIB_error(const enum _ErrEnum ErrMsgNum);

// print formatted error messages
void SIMLIB_error(const char *fmt, ... );

// print internal error messages
void SIMLIB_error(const char *file, const int line);
#define SIMLIB_internal_error() SIMLIB_error(__FILE__, __LINE__)

// print warnings
void SIMLIB_warning(const enum _ErrEnum ErrMsgNum);

////////////////////////////////////////////////////////////////////////////
// types:
//
typedef void (*VoidFunctionPtr)(); // ptr to void function


////////////////////////////////////////////////////////////////////////////
// internal variables:
//

extern bool SIMLIB_DynamicFlag;             // in dynamic section
extern bool SIMLIB_ResetStatus;             // restart flag

extern SIMLIB_Phase_t SIMLIB_Phase;         // phase of simulation experiment

extern Entity *SIMLIB_Current;              // currently active entity

extern int SIMLIB_ERRNO;                    // error number

extern bool SIMLIB_ConditionFlag;           // change of condition vector
extern bool SIMLIB_ContractStepFlag;        // requests shorter step
extern double  SIMLIB_ContractStep;         // requested step size

extern double SIMLIB_StepStartTime;         // last step time
extern double SIMLIB_DeltaTime;             // Time-s_StepStartTime

extern double SIMLIB_OptStep;               // optimal step
extern double SIMLIB_MinStep;               // minimal step
extern double SIMLIB_MaxStep;               // max. step
extern double SIMLIB_StepSize;              // actual step

extern double SIMLIB_AbsoluteError;         // absolute error
extern double SIMLIB_RelativeError;         // relative error

extern double SIMLIB_StartTime;       // time of simulation start
extern double SIMLIB_Time;            // simulation time
extern double SIMLIB_NextTime;        // next-event time
extern double SIMLIB_EndTime;         // time of simulation end

// calendar interface
class SQS { 
    static void ScheduleFirst(Entity *e);       // first in calendar
    static void ScheduleAt(Entity *e, double t);// time t
    static Entity *Get(Entity *e);              // remove entity p
    friend class Entity;
    friend class Process;
  public: // for Run(), Init()
    static bool Empty();                        // ?empty calendar
    static void Clear();                        // remove all items
    static Entity *Current();                   // reference to first item
    // for Facility???
    static double ActivationTime(Entity *e);    // activation time
};

// macro for simple assignement to internal time variables
#define _SetTime(t,x) (SIMLIB_##t = x)

void SIMLIB_Dynamic();               // optimize!
void SIMLIB_DoActions();             // dispatch events and processes
void SIMLIB_ContinueInit();          // initialize variables
void SIMLIB_DoConditions();          // perform state events
//void SIMLIB_GraphInit();             // graph activation
void SIMLIB_WUClear();               // clear WUList



//////////////////////////////////////////////////////////////////////////
// MACROS --- Hooks into simulation control algorithm
//
// we use static pointers to void function()
// function can be installed by calling INSTALL_HOOK(hook_name,function)
// used mainly in run.cc

// definition of hook-pointer-variable name and hook-install-function name
// the names are internal and _can_ be changed here:
#define HOOK_PTR_NAME(id)  SIMLIB_Hook_Ptr_##id
#define HOOK_INST_NAME(id)  SIMLIB_Install_hook_##id

/////////////////////////////////////////////////////////////////////////////
// INSTALL_HOOK --- macro for hook function installation
// parameters:
// 	name of hook
// 	function to install as hook -- prototype should be: void f();
//
#define INSTALL_HOOK(name,function) do {\
	void HOOK_INST_NAME(name) (void (*f)()); /* prototype */ \
        HOOK_INST_NAME(name)(function);  /* call of installer */ \
	}while (0)

    
/////////////////////////////////////////////////////////////////////////////
// DEFINE_HOOK --- macro for hook definition
// parameter:
// 	name of hook
// can be used at global scope
//
#define DEFINE_HOOK(name)  \
        static void (* HOOK_PTR_NAME(name) )() = 0; \
        void HOOK_INST_NAME(name)(void (*f)())  { HOOK_PTR_NAME(name) = f; }

	
/////////////////////////////////////////////////////////////////////////////
// CALL_HOOK --- macro for checked hook calling
// parameter:
// 	name of hook
// can be used in the same module as DEFINE_HOOK (static) 	
//
#define CALL_HOOK(name)  \
        if( HOOK_PTR_NAME(name) )  HOOK_PTR_NAME(name) ()


////////////////////////////////////////////////////////////////////////////
//  auxiliary functions ### remove
//
inline double min(double a, double b) { return ((a)>(b)?(b):(a)); }
inline double max(double a, double b) { return ((a)>(b)?(a):(b)); }

// NAME subsystem - experimental
const char *SIMLIB_create_name(const char *fmt, ...);

#endif //__SIMLIB__INTERNAL_H__

// end

