/*******************************************************************
*  DESCRIPTION: Atomic Model admin
*  AUTHOR: Emad Khan
*  EMAIL: emadkhan@cmail.carleton.ca
*  DATE: 30/10/2016
*******************************************************************/

#include "admin.h"      // class admin
#include "message.h"    // class Message
#include "mainsimu.h"   //

/** public functions **/

/*******************************************************************
* Function Name: Administration Office
********************************************************************/
admin::admin( const string &name )
: Atomic( name )
, newclt( addInputPort( "newclt" ) ) //Represent Input of New Client coming into the food bank
, nxtclt( addInputPort( "nxtclt" ) ) //Represent Input of Next Client to proceed into the food bank
, order( addOutputPort( "order" ) )  //Represent Output of Order to Distribution Centre

, openHrs( 9, 0, 0, 0 ) //Opening time 9:00AM
, closeHrs( 13, 0, 0, 0 ) //Closing time 1:00PM
, numberofSeats( 7 ) // Number of Seats = 10
, prepTime( 0, 0, 0, 0 ) //No preparation time required at the beginning

{
   initInt = ( MainSimulator::Instance().getParameter( description(), "numberofSeats" ) ) ; //Check if parameter numberofSeats is defined in model file
	if(initInt != "") //Check if integer type
		numberofSeats = str2Int(initInt) ; //Convert string type to integer type

	string time = ( MainSimulator::Instance().getParameter( description(), "prepTime" ) ) ; //Check if parameter prepTime is defined in model file
	if( time != "" )
		prepTime = time ;
	time = ( MainSimulator::Instance().getParameter( description(), "openHrs" ) ) ; //Check if parameter openHrs is defined in model file
	if( time != "" )
		openHrs = time ;
	time = ( MainSimulator::Instance().getParameter( description(), "closeHrs" ) ) ; //Check if parameter closeHrs is defined in model file
	if( time != "" )
		closeHrs = time ;
}

/*******************************************************************
* Function Name: initFunction
********************************************************************/
Model &admin::initFunction()
{
   full_space = false ; //FoodBank is initially empty
   clt_is_ready = false ; //Client is ready
	elements.erase( elements.begin(), elements.end() ) ;
	return *this ;
}

/*******************************************************************
* Function Name: externalFunction
********************************************************************/
Model &admin::externalFunction( const ExternalMessage &msg )
{
	//For message at port newclt
	if( msg.port() == newclt ){
      if    ( (msg.time().asMsecs() - Time(openHrs).asMsecs() < 0) || (msg.time().asMsecs() - Time(closeHrs).asMsecs() > 0) ){}//Condition if out of working hours

      else {

    	  if (!(elements.size() < numberofSeats)){}   //Condition if clients more than No. of Seats

    	  else {
    		  elements.push_back( abs((int)msg.value()) ) ; //Condition if clients arrives

             if (elements.size() == 1) //Condition for first client being processed
             {
                holdIn( active, prepTime ) ; //Hold state active for the preparation time
             }

             else {}
         }
      }
   }

	//For message at port nxtclt
	if (msg.port() == nxtclt)
	{
		//cout << lastChange() << "Admin Office - Activate Queue - Request for Next Client: " << elements.size() << " : " << elements.front() << "\n" ;
		holdIn( active, prepTime ) ;
	}
	return *this;
}

/*******************************************************************
* Function Name: internalFunction
********************************************************************/
Model &admin::internalFunction( const InternalMessage & )
{
    //cout << lastChange() << "Admin Office - Internal Transition : " << elements.size() << " : " << elements.front() << "\n" ;
	passivate(); //Passivates the model
	return *this ;
}

/*******************************************************************
* Function Name: outputFunction
********************************************************************/
Model &admin::outputFunction( const InternalMessage &msg )
{
   if (elements.size()){
	   //cout << lastChange() << "Admin Office - Output Transition : " << elements.size() << " : " << elements.front() << "\n" ;
	   sendOutput( msg.time(), order, elements.front() ) ;
	   elements.pop_front();
   }

   else {
	   //cout << lastChange() << "Admin Office - Output Transition - No Client: " << elements.size() << " : " << elements.front() << "\n" ;
   }
	return *this ;
}
