/* 
   Project: coevolutionary GP moto driving
   Dana Vrajitoru
   driver_animate.h
   
   The class that handles all possible movements of the body of the
   driver.
  
**/

#ifndef DRIVER_ANIMATE_H
#define DRIVER_ANIMATE_H

#include "driver_geometry.h"
#include <fstream>
using namespace std;

enum angles_ids { 
  position=0, rotation, angle_head, angle_shoulders, 
  angle_arm_left, angle_arm_right, angle_elbow_left, angle_elbow_right,
  angle_wrist_left, angle_wrist_right, 
  angle_hips_center,
  angle_hips_left, angle_hips_right, angle_knee_left, angle_knee_right,
  angle_ankle_left, angle_ankle_right
};

const int vector_numbers=angle_ankle_right+1;

class Driver_animate: public Driver_geometry {

 protected:
  vector3f vectors;
  int name_id;

 public:
  Driver_animate(float size=5, int name=0);

  ~Driver_animate();

  // Inialize the position. Default values 0, 0, 0.
  void set_position(float x=0, float y=0, float z=0);
  void set_position(Point3f &pos);
  // Translate from the original position by some values.
  void add_position(float x, float y, float z);
  void add_position(Point3f &pos);
  void remove_position(Point3f &pos);
  // Inialize the rotation. Default values 0, 0, 0.
  void set_rotation(float ax=0, float ay=0, float az=0);
  // Add some values to the initial rotation.
  void add_rotation(float ax, float ay, float az);

  // Set all the angles to 0.
  void reset_angles();

  // Print a snaphot of all the angles.
  void print_angles();

  // Output a snaphot of all the angles to a file.
  void output_angles(ofstream &fout);

  // Some weird angle values to test the model. Thought it was worth
  // saving.
  void test_angles();

  // Some particular functions that describe the mobility of the body.
  void bend_left_knee(float angle);
  void bend_right_knee(float angle);
  void bend_knees(float angle);

  void rotate_left_thigh_up(float angle);
  void rotate_right_thigh_up(float angle);
  void rotate_thighs_up(float angle);

  void rotate_left_thigh_out(float angle);
  void rotate_right_thigh_out(float angle);
  void rotate_thighs_out(float angle);

  void rotate_left_arm_up(float angle);
  void rotate_right_arm_up(float angle);
  void rotate_arms_up(float angle);

  void rotate_left_arm_out(float angle);
  void rotate_right_arm_out(float angle);
  void rotate_arms_out(float angle);

  void bend_left_forearm(float angle);
  void bend_right_forearm(float angle);
  void bend_forearms(float angle);

  // Move some angles based on an identity. 
  void move_angle(int id, int coord, float quant);

  // Builds the display lists.
  virtual void draw();

  // Applies some general purpose translation and rotation to make the
  // entire scene follow the driver around.
  void set_view();

  // Calls any display list and identifies the name of the primitives
  // too for interactive purposes.
  void call_list_name(int id, int name);

  // Calls the display lists with appropriate transformations.
  virtual void display();

  // Display one leg with given angles and position.
  void display_leg(angles_ids angle_hips, angles_ids angle_knee, 
		   angles_ids angle_ankle,
		   float x_trans, float y_trans);
  // Display one arm with given angles and position.
  void display_arm(angles_ids angle_arm, angles_ids angle_elbow, 
		   angles_ids angle_wrist,
		   float x_trans, float y_trans);

  // This function generates a mirror left-right image of the current pose.
  void Driver_animate::reverse_angles();
};

#endif
