// main.cc: the file containing the main() function.

#include <cstdio>
#include <iostream.h>
#include "random.h"
#include "stats.h"
#include "car.h"
#include "carqueue.h"
#include "pump.h"
#include "pstand.h"
#include "event.h"
#include "evlist.h"
#include "main.h"
#include "arrival.h"
#include "endsim.h"
#include "report.h"

// Here is the actual definition of the global variable declared in
// "main.h". It is instantiated within the function main().

Sim *sim;

int main()
{
   sim = new Sim();

   // Initialize the constant fields of sim. These are values that could be
   // read from input but that are fixed throughout because this model is
   // intended as a simple example.
   sim->profit = 0.025;
   sim->pumpCost = 20;
   sim->litresNeededMin = 10;
   sim->litresNeededRange = 50;
   sim->serviceTimeBase = 150;
   sim->serviceTimePerLitre = 0.5;
   sim->serviceTimeSpread = 30;
   sim->balkA = 40;
   sim->balkB = 25;
   sim->balkC = 3;
   sim->meanInterarrivalTime = 50;

   // Read data and print introduction.
   scanf ("%lg", &sim->reportInterval);
   double endingTime; // How long should the simulation run?
   scanf ("%lg", &endingTime);
   int numPumps; // How many pumps does the pump stand have?
   scanf ("%d", &numPumps);
   cout << "This simulation run uses " << numPumps << " pumps ";

   // Initialize the random-number streams.
   cout << "and the following random number seeds:\n";
   int seed;
   scanf ("%d", &seed);
   sim->arrivalStream = new Random (seed);
   cout << "         " << seed;
   scanf ("%d", &seed);
   sim->litreStream = new Random (seed);
   cout << "         " << seed;
   scanf ("%d", &seed);
   sim->balkingStream = new Random (seed);
   cout << "         " << seed;
   scanf ("%d", &seed);
   sim->serviceStream = new Random (seed);
   cout << "         " << seed;
   cout << "\n";

   // Create and initialize the event list, the car queue, the pump stand,
   // and the statistics collector.
   sim->eventList = new EventList ();
   sim->carQueue = new CarQueue ();
   sim->pumpStand = new PumpStand (numPumps);
   sim->stats = new Statistics ();

   // Schedule the required events:
         //   the end of the simulation;
         //   the first progress report;
         //   the arrival of the first car.
   EndOfSimulation *lastEvent = new EndOfSimulation (endingTime);
   sim->eventList->insert (lastEvent);
   if (sim->reportInterval <= endingTime) {
      Report *nextReport = new Report (sim->reportInterval);
      sim->eventList->insert (nextReport);
   }
   sim->eventList->insert (new Arrival (0));
      // (Should the first car really arrive at time 0?)

   // The "clock driver" loop
   sim->simulating = 1;
   while (sim->simulating) {
      Event *currentEvent = sim->eventList->takeNextEvent();
      sim->simulationTime = currentEvent->getTime();
      currentEvent->makeItHappen();
      // We could replace the "instanceof" operator in the Java
      // version by C++'s dynamic_cast operator, as in the following
      // line; but that's fairly advanced C++, so I've chosen to
      // let the EndOfSimulation event modify a global variable instead.
      // if (dynamic_cast<EndOfSimulation *>(currentEvent)) break;
   }   

   return 0;
}

