/* 
   Project: coevolutionary GP moto driving
   Dana Vrajitoru
   pilot_manager.h
   
   The class that manages the automatic pilot.
  
**/

#ifndef PILOT_H
#define PILOT_H

enum Pilot_status {
  run_once_st = 0, run_many_st, complete_st,
  incomplete_st, crashed_st, lost_st
};

enum Event_id { 
  null_evt = 0, update_evt, turn_on_evt, turn_off_evt, terminate_evt 
};

enum Agent_type {
  update_agt=0, gas_agt, breaks_agt, steer_agt
};

class Agent;
class Manager;
typedef Agent *Agent_ptr;

class Pilot_manager {
 protected:
  Agent **components;
  int nr_agents;
  float tic;
  Manager *boss;
  bool sequential;

  // Sends the same event to all the agents
  void broadcast_event(Event_id the_event);

 public:
  float speed_limit;

  pthread_mutex_t mutex, mutex_evt;
  Event_id event;
  
  int count[5];

  // Default constructor.
  Pilot_manager();
  // Constructor with known manager. Only the individual components
  // need to know what this is.
  Pilot_manager(Manager *the_boss, float timing=0.01);
  // Creates the agents with the appropriate classes.
  void new_agents();
  // Desctructor. 
  ~Pilot_manager();

  // Set the manager is we find out about it afterwards.
  void set_manager(Manager *the_boss);
  // To reset the timing lapse
  void set_timing(float timing);
  // Set the speed limitation.
  void set_speed_limit(float speed);

  // Read the constants and thresholds from the configuration file.
  void read(char *filename);
  void read_param(double *param_arr, int param_size);

  // Launch all the agents.
  void launch();

  // Turns all the agents on.
  void turn_on();
  
  // Turns all the agents off.
  void turn_off();
  
  // Terminates all the agents.
  void terminate();

  // Locks the mutex while we move the motorcycle from the exterior.
  void lock();

  // Unlock the mutex when we're done.
  void unlock();

  // Locks the event mutex.
  void lock_evt();

  // Unlock the event mutex when we're done.
  void unlock_evt();

  // Turn the sequential flag on and off.
  void make_seq();
  void make_multi_thr();

  // A sequential probabilistic update.
  void sequential_update();
};

#endif
