// ========================================================================================
// You will complete the Simulator class.
// You may edit this file as needed.
// ========================================================================================

#ifndef __SIMULATOR_H__
#define __SIMULATOR_H__

#include <vector>
#include <queue>
#include <fstream>
#include <queue>

#include "timestamp.h"
#include "job.h"

// The simulator class stores a queue of student submissions awaiting
// autograding, manages which jobs are currently assigned to each
// processor, and tracks statistics to facilitate the analysis of the
// scheduling algorithm.

class Simulator {
public:
  
  // CONSTRUCTOR
  Simulator(const TimeStamp &simulation_start_time, int num_processors,
            double timestep, bool prioritize_by_niceness,
            const std::string &visualization_file, const std::string &log_file);

  // ACCESSORS
  const TimeStamp& getCurrentTime() { return current; }
  int timestepMilliseconds(const TimeStamp &next_upload=TimeStamp(0,0,0,0)) const;
  void tickMilliseconds(int ms) { current.addMilliseconds(ms); }
  
  // FUNCTIONS RELATED TO THE JOBS QUEUE
  int numJobsTodo() const;
  void addJob(Job j);
  Job peekNextJob();
  void removeNextJob();

  // FUNCTIONS RELATED TO THE SIMULATION
  void cleanupJobs();
  void startJobs();
  bool simulationComplete() const;
   
  // FUNCTIONS FOR PRINTING
  void printVisualizationRow();
  void printJobToLog(const Job &h, int which_processor);
  void printSummaryStatistics(double simulation_running_time);
  
private:

    // REPRESENTATION
  TimeStamp current;
  int num_processors;
  int timestep_milliseconds;
  bool prioritize_by_niceness;
  std::ofstream vis_str;
  std::ofstream log_str;
  std::vector<Job> processors;

  // the STL queue type is a FIFO queue, 
  std::queue<Job> todo_list;

  
  // 
  // ASSIGNMENT: You'll need to create member variables for the two
  // STL priority_queues.
  //
  
  
  // statistics
  long long int job_count;
  double max_waiting_time;
  double total_waiting_time;
  double non_idle_time;
  std::vector<double> nice_total_waiting_times;
  std::vector<int> nice_waiting_counts;
};

#endif
