//=========================================================================
// Summary  :
// Filename : ProcessList.cc
// Author   : marsh
// Project  :
// Revision : 1
// Created  : 2000/08/19
// Modified : 2000/08/19
//=========================================================================
// Description :
//=========================================================================

#include "System.h"
#include "Syslog.h"

#include "StringAttribute.h"
#include "DebugAttribute.h"

#include "Process.h"
#include "Device.h"
#include "ProcessList.h"

#include "AttributeParser.h"


ProcessList::ProcessList( Boolean isSim )
     : ItemList( PROCESS_LIST_ID ),
       attributes( "ProcessList" )
{
     _currentStratum = 0;

     _isSim = isSim;

     _devicesFile = NULL;
     _simDevicesFile = NULL;

     _lastIdentifier = ProcessId;

     // Only make the relevant attribute mandatory, depending on
     // whether we're sim or not
     attributes.add(
	  new StringAttribute("devicesFile",
			      "File containing list of real devices",
			      &_devicesFile,
			      (_isSim)?"":NULL ) );
     attributes.add(
	  new StringAttribute("simDevicesFile",
			      "File containing list of simulated devices",
			      &_simDevicesFile,
			      (_isSim)?NULL:"" ) );

     attributes.add( new DebugAttribute("defaultDebug",
					"Default debug level",
					&_defaultDebug,
					DEBUG_T_MIN ) );

}

ProcessList::~ProcessList()
{
    clean( _devicesFile );
    clean( _simDevicesFile);
}

Boolean ProcessList::isIdentifier( const char *checkMe )
{
     Boolean debug = False;

     if( !strcmp( checkMe, "process" ) ) {
	  dprintf("ProcessList::isidentifier -- Found the identifier \"process\"");
	  _lastIdentifier = ProcessId;
	  return True;
     } else if( !strcmp( checkMe, "device" ) ) {
	  dprintf("ProcessList::isidentifier -- Found the identifier \"device\"");
	  _lastIdentifier = DeviceId;
	  return True;
     }

     return False;
}


Item *ProcessList::addItem( const char *name )
{
     Boolean debug = False;
     int index;
     Process *newProcess;

     switch(_lastIdentifier) {
     case ProcessId:
	  dprintf("ProcessList -- Adding a new process of name %s", name );
	  newProcess = new Process( name, _currentStratum,
				    _defaultDebug );
	  break;
     case DeviceId:
	  dprintf("ProcessList -- Adding a new device of name %s", name );
	  newProcess = new Device( name, _currentStratum,
				   _defaultDebug );
	  break;
     default:
	  return NULL;
     }

     index = _itemList.add( (Item * *)&newProcess );

     dprintf("ProcessList -- Added new %s with name %s",
	     (_lastIdentifier==ProcessId)?"process":"device",
	     newProcess->name() );

     return newProcess;
}

int ProcessList::loadProcesses( const char *baseFilename )
{
     Boolean debug = True;

     const char *fullFilename = System::configurationFile( baseFilename );

     dprintf("ProcessList::loadProcesss -- "
		   "Starting load of device list ");
     Syslog::write("Using device config file %s\n", fullFilename );

     AttributeParser::reset();

     _currentStratum = 0;

     if( loadProcessFile( fullFilename, True ) ) {
	  Syslog::write("ProcessList::loadProcess -- "
			"Failed to load core process list" );
	  return -1;
     }

     if( _isSim )
	 fullFilename = System::configurationFile( _simDevicesFile );
     else
	 fullFilename = System::configurationFile( _devicesFile );
     
     dprintf("ProcessList::loadProcess -- "
	     "%s: Loading device file %s",
	     (_isSim)?"Sim mode":"Real mode", fullFilename );

     _currentStratum = 1;

     if( loadProcessFile( fullFilename, False ) ) {
	  Syslog::write("ProcessList::loadProcess -- "
			"Failed to load device process list" );
	  return -1;
     }

     if( debug ) {
	  dprintf("Process list from %s", fullFilename );
	  dumpProcessList();
     }

     return 0;


}

int ProcessList::loadProcessFile( const char *fullFilename, Boolean topLevel )
{
     try {
	  if( topLevel )
	       AttributeParser::parse( fullFilename, &attributes, this );
	  else
	       AttributeParser::parse( fullFilename, this );
     }
     catch(Exception e)
     {
	  Syslog::write("ProcessList::loadProcesss -- AttributeParser "
			"threw: %s",
			e.msg );
	  return -1;
     }
     catch(...)
     {
	  Syslog::write("ProcessList::loadProcesss -- AttributeParser "
			"threw an unknown exception");

	  return -1;
     }

     int bad = 0;
     if( (bad = verify()) ) {
	  Syslog::write("ProcessList::loadProcesss -- %d devices didn't load "
			"properly -- exiting.", bad );
	  return -1;
     }

     return 0;
}

void ProcessList::dumpProcessList()
{
     Process *current;

     for( int i = 0; i < _itemList.size(); i++ ) {
	  _itemList.get(i,(Item * *)&current);
	  Syslog::write("%d:\t%s\t%d",
			i, current->name(),
			current->priority() );

     }
}

short ProcessList::findIndexByPid( short pid )
{
	Process *current;

	for( int i = 0; i < _itemList.size(); i++ ) {
		_itemList.get(i,(Item * *)&current);

		if( current->pid() == pid )
		{
			return i;
		}

	}
	return -1;
}
