// CSC 270 simulation example
// -- J. Clarke, March-June 1996

#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>

#include "world.h"
#include "event.h"
#include "evlist.h"
#include "car.h"
#include "carqueue.h"
#include "pump.h"
#include "pstand.h"
#include "stats.h"
#include "arrival.h"
#include "pseudev.h"

// Global variables
// ----------------
//
// Should all these be global? How could you make them non-global?

double simulationTime; // the current time
statsClass * stats; // holds accumulated statistics
eventListClass * eventList; // the event list
pumpStandClass * pumpStand; // the pumps at the gas station
carQueueClass * carQueue; // the queue of waiting cars

// If there is a command-line argument, it should be the name of
// a file to be used for input.

int main (int argc, char *argv[])
{
	FILE *infile = stdin;

	// Check for file-opening request.
	if (argc > 2) {
		cout << "Usage: sim [infile]\n";
		return EXIT_FAILURE;
	}
	if (argc == 2) {
		infile = fopen (argv[1], "r");
		if (infile == NULL) {
			cout << "sim: can't open \"" << argv[1] << "\".\n";
			return EXIT_FAILURE;
		}
	}

	//---------------
	// Initialization
	//---------------

	const double profit = .025; // dollars per litre
	const double cost = 20;
		// the incremental cost in dollars to operate one pump for a day

	// The controls read as input.

	double ReportInterval, endingTime;
	fscanf (infile, "%lf %lf", &ReportInterval, &endingTime);

	int numPumps;
	fscanf (infile, "%d", &numPumps);
	cout << "This simulation run uses " << numPumps << " pumps ";
	pumpStand = new pumpStandClass (numPumps);

	worldsetup (infile, stdout); // Initialize the "world model."

	// Create and initialize the event queue, the car queue,
	// and the statistical variables.

	eventList = new eventListClass;
	carQueue = new carQueueClass;
	stats = new statsClass (profit, cost);

	// Schedule the end-of-simulation and the first progress report.

	allDoneClass * lastEvent = new allDoneClass (endingTime);
	eventList -> insert (lastEvent);
	if (ReportInterval <= endingTime) {
		reportClass * nextReport = new reportClass (ReportInterval);
		nextReport -> setInterval (ReportInterval);
		eventList -> insert (nextReport);
	}

	// Schedule the first car to arrive at the start of the simulation

	arrivalClass * nextArrival = new arrivalClass (0);
		// Is 0 really the time for the first arrival?
	eventList -> insert (nextArrival);

	// Column headings
	stats -> header ();

	//------------------------
	// The "clock driver" loop
	//------------------------

	simulationTime = 0.0;
	bool simulating = true;
	while (simulating) {
		eventClass * currentEvent = eventList -> getNext ();
		simulationTime = currentEvent -> whatTime ();
		simulating = currentEvent -> makeItHappen ();
	}

	return 0;
}
