/* 
   Project: coevolutionary GP moto driving
   Dana Vrajitoru
   agent.h
   
   A base class for an agent controling one unit of the automatic
   pilot.
  
**/

#ifndef AGENT_H
#define AGENT_H

#include <pthread.h>
#include "pilot_manager.h"

class Agent {
 protected:
  bool is_on;
  Manager *boss;
  Pilot_manager *parent;
  float speed_limit;
  float moto_length;
  int nr_config;

  // Status type of values to be taken from the manager.
  float left_dist, right_dist, front_dist, slope, speed;
  float forward_left_dist, forward_right_dist;
  float front_left_dist, front_right_dist;

  float tic;
  int my_id;
  pthread_t the_thread;
  // This will be specific to each agent.
  virtual void update_action();
  // This may be reimplemented by the agent if anything special must
  // be done when it is turned on.
  virtual void turn_on_action();
  // This may be reimplemented by the agent if anything special must
  // be done when it is turned off.
  virtual void turn_off_action();
  // Filling in the status values from the manager.
  void get_status();
  // Print out these values.
  void print_status();
  // Set the number of configuration values. To be defined by the
  // derivate classes.
  virtual void set_nr_config();

 public:
  // Default constructor. Not much to do.
  Agent(float timing=0);
  // Constructor for which we know the manager.
  Agent(Manager *the_boss, float timing=0);
  // Destructor: nothing to do for now.
  ~Agent();

  // output the values
  virtual void output_data();

  // To be called if we find out who the boss is later.
  virtual void set_manager(Manager *the_boss);
  // To reset the timing lapse
  void set_timing(float timing);
  // Set the id of this agent.
  void set_id(int id);
  // Set the pilot manager.
  virtual void set_parent(Pilot_manager *pilot);
  // Set the speed limit.
  void set_speed_limit(float speed);
  // Agent-specific set data to be defined in the derivate class.
  virtual void set_data(float values[]);

  // Very important. This function creates a new thread for this agent
  // and sends it into the main loop.
  void launch();
  
  // Synchronises the termination of all the threads.
  void join();

  virtual void main_loop();

  friend class Manager;
  friend class Pilot_manager;
  friend class Agent_steering;
};

void *launch_agent(void *agnt);

#endif
