/////////////////////////////////////////////////////////////////////////////
// entity.cc
//
// 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.
//

//
// description: base class of the entity hierarchy
//

////////////////////////////////////////////////////////////////////////////
// interface
//

#include "simlib.h"
#include "internal.h"

////////////////////////////////////////////////////////////////////////////
// implementation
//

SIMLIB_IMPLEMENTATION

#define CHECKENTITY(e) if (!e) SIMLIB_error(EntityRefError);
#define CHECKQUEUE(q) if (!q) SIMLIB_error(QueueRefError);

static unsigned long SIMLIB_Entity_Count = 0L; // # of entities in model
unsigned long Entity::_Number = 0L;     // # of entity creations

////////////////////////////////////////////////////////////////////////////
//  constructor
//
Entity::Entity(Priority_t p) :
  _Ident(SIMLIB_Entity_Count++), // unique identification
  _MarkTime(0.0), 
  _SPrio(0),
  Priority(p),
  _Ev(0)
{
  _Number++;                      // # of entities
  dprintf(("Entity#%lu{%p}::Entity(%d)", _Ident, this, p));
}

////////////////////////////////////////////////////////////////////////////
//  destructor
//
Entity::~Entity() {
  dprintf(("Entity#%lu{%p}::~Entity()", _Ident, this));
  if (!Idle()) {
    SQS::Get(this);           // remove from calendar
//  _warning(DeletingActive); // not important!!!??? if sim SIMLIB_error else _warn
  }
  _Number--;                 // # of entities in model
}

////////////////////////////////////////////////////////////////////////////
//  Activate - entity activation
//
void Entity::Activate()      // activate now
{
  dprintf(("%s.Activate()", Name()));
  Activate(Time);
}

void Entity::Activate(double t)
{
  dprintf(("%s.Activate(%g)", Name(), t));
  CHECKENTITY(this);
  SQS::ScheduleAt(this,t);
}

#if 0
////////////////////////////////////////////////////////////////////////////
//  Wait - waiting in queue
//
void Entity::Wait(Queue *q)
{
  dprintf(("%s.Wait(%s)",Name(),q->Name()));
  CHECKENTITY(this);
  CHECKQUEUE(q);
  q->Insert(this); // insert into queue q
  Passivate();     // deactivate
}
#endif

////////////////////////////////////////////////////////////////////////////
//  Wait - wait for dtime
//
void Entity::Wait(double dtime)
{
  dprintf(("%s.Wait(%g)",Name(),dtime));
  Activate(double(Time)+dtime);  // scheduling
}

////////////////////////////////////////////////////////////////////////////
//  Passivate - deactivation of process (entity)
//
void Entity::Passivate()
{
  dprintf(("%s.Passivate()",Name()));
  CHECKENTITY(this);
  if(!Idle()) SQS::Get(this);   // remove from calendar
}


////////////////////////////////////////////////////////////////////////////
// Into --- inserting into queue
//
#if 0
void Entity::Into(Queue *q)
{
  CHECKQUEUE(q);
  if(where()!=0) Out(); // if already in queue then remove ### +warning ???
  q->Insert(this);      // insert
}
#endif 

////////////////////////////////////////////////////////////////////////////
//  Out - leaving queue
//
void Entity::Out()
{
  Link::Out(); // equal
}

////////////////////////////////////////////////////////////////////////////
//  Terminate -- passivate & destroy entity
//
void Entity::Terminate()
{
  dprintf(("%s.Terminate()",Name()));
  if(!Idle()) SQS::Get(this);    // remove from calendar and/or queue ????
  if(IsAllocated()) delete this;   // destroy entity
}

////////////////////////////////////////////////////////////////////////////
//  Entity::Name
//
const char *Entity::Name()
{
  const char *name = SimObject::Name();
  if(*name) return name; // return explicit name
  else      return SIMLIB_create_name("Entity%lu{%p}", _Ident, this);
}

// end

