//  Robot_Driver.h - a computer-controlled driver
//
//	Vamos Automotive Simulator
//  Copyright (C) 2008 Sam Varner
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#ifndef _ROBOT_DRIVER_H_
#define _ROBOT_DRIVER_H_

#include "Controls.h"
#include "Driver.h"
#include "../geometry/PID.h"
#include "../geometry/Spline.h"

namespace Vamos_Geometry
{
  class Three_Vector;
}

namespace Vamos_Track
{
  class Strip_Track;
  class Gl_Road_Segment;
}

namespace Vamos_World
{
  class Robot_Driver : public Driver
  {
  public:
    Robot_Driver (Vamos_Body::Car* car_in, Vamos_Track::Strip_Track* track_in);

    // Step the driver forward in time.
    virtual void propagate (double time_step);

    virtual void draw ();

  private:
    enum State
      {
        PARKED,
        STARTING,
        DRIVING
      };


    // The point that is kept on the racing line is this far ahead of the
    // car.
    double target_distance () const;

    // The position of the point that the driver tries to keep on the racing line.
    Vamos_Geometry::Three_Vector target_position () const;

    void steer (double time_step, const Vamos_Geometry::Three_Vector& track_position);
    void shift (double time_step);
    void accelerate (double time_step, const Vamos_Geometry::Three_Vector& track_position);

    const Vamos_Track::Gl_Road_Segment& current_segment () const;
    const Vamos_Track::Gl_Road_Segment& next_curve (int index = -1) const;
    const Vamos_Track::Gl_Road_Segment& previous_curve (int index = -1) const;
    double longitudinal_slip () const;
    double transverse_slip () const;
    double speed () const;
    bool on_curve (double along) const;
    void change_speed (double time_step, const Vamos_Geometry::Three_Vector& track_position); 
    double velocity_margin ();
    double stopping_distance () const;
    double racing_line_speed (double distance);
    double stopping_speed (double distance) const;

    // Return the speed-dependent performance parameters.
    double deceleration () const;
    double lateral_acceleration () const;

    Vamos_Geometry::PID m_steer_control;
    Vamos_Geometry::PID m_gas_control;

    // Parameters from the car.
    double m_slip_ratio;
    std::vector <double> m_deceleration;
    std::vector <double> m_lateral_acceleration;

    size_t m_road_index;
    size_t m_segment_index;
    Vamos_Track::Strip_Track* mp_track;
    bool m_reset;
    double m_shift_time;
    State m_state;
    double m_state_time;
  };
}

#endif // not _ROBOT_DRIVER_H_
