#ifndef _GL_ROAD_SEGMENT_H_
#define _GL_ROAD_SEGMENT_H_

#include <vamos/track/Road_Segment.h>

#include <GL/glu.h>

#include <string>
#include <vector>

namespace Vamos_Media
{
  class Texture_Image;
  class Facade;
}

namespace Vamos_Track
{
  class Braking_Marker
  {
    Vamos_Media::Facade* mp_image;
    double m_distance;
    Vamos_Geometry::Side m_side;
    double m_from_edge;
    double m_off_ground;

  public:
    Braking_Marker (std::string image_file,
                    double distance,
                    Vamos_Geometry::Side side,
                    double from_edge,
                    double off_ground,
                    double width,
                    double height);
    ~Braking_Marker ();

    double distance () const { return m_distance; }
    Vamos_Geometry::Side side () const { return m_side; }
    double from_edge () const { return m_from_edge; }
    double off_ground () const { return m_off_ground; }
    double width () const;
    double height () const;
    void draw () const;
  }; 

  class Gl_Road_Segment : public Road_Segment
  {
  public:
	struct Model_Info
	{
	  std::string file;
	  double scale;
	  Vamos_Geometry::Three_Vector translation;
	  Vamos_Geometry::Three_Vector rotation;
	};

  private:
	std::vector <Model_Info> m_models;
	
	enum 
	  { 
		LEFT_BARRIER, 
		LEFT_SHOULDER, 
		LEFT_KERB,
		TRACK, 
		RIGHT_KERB,
		RIGHT_SHOULDER,
		RIGHT_BARRIER
	  };

	GLuint* m_gl_texture_name;
	GLuint m_gl_list_id;
	std::vector <GLuint> m_scenery_lists;

	std::vector <double> m_texture_offsets;

	struct Segment_Iterator
	{
	  Segment_Iterator (double res, size_t strips);

	  void start (const Vamos_Geometry::Three_Vector& start_coords,
				  double start_angle);

	  Vamos_Geometry::Three_Vector coordinates;
	  Vamos_Geometry::Two_Vector texture_coordinates;
	  Vamos_Geometry::Three_Vector normal;

	  double resolution;
	  double distance;
	  double angle;
	  bool left_side;

	  // True when we're rendering the first subdivision.
	  bool first;
	  // True when we're rendering the last subdivision.
	  bool last;

	  // The current substrip.
	  size_t substrip;
	};

	Segment_Iterator* mp_iterator;

	void draw_strip (size_t i, double texture_offset);

	std::vector <Braking_Marker*> m_braking_markers;

    void add_textures ();

    std::vector <Vamos_Media::Texture_Image*> m_textures;


	// bounding dimensions
	double m_min_x;
	double m_min_y;
	double m_max_x;
	double m_max_y;


	void increment_kerb_distance (const Kerb& kerb);


  public:
	Gl_Road_Segment (double resolution, double length, 
                     double radius, double skew, 
                     const std::vector <Vamos_Geometry::Two_Vector>& 
                     left_width, 
                     const std::vector <Vamos_Geometry::Two_Vector>& 
                     right_width, 
                     const std::vector <Vamos_Geometry::Two_Vector>& 
                     left_road_width, 
                     const std::vector <Vamos_Geometry::Two_Vector>& 
                     right_road_width, 
                     Kerb* left_kerb, Kerb* right_kerb,
                     double left_wall_height, double right_wall_height,
                     const std::vector <Vamos_Geometry::Two_Vector>& 
                     elevation_points,
                     const std::vector <Vamos_Geometry::Two_Vector>& 
                     bank_points,
                     double end_bank, double bank_pivot,
                     const std::vector <Vamos_Geometry::Material>& 
                     materials,
                     const std::vector <Braking_Marker*>& braking_markers);

    ~Gl_Road_Segment ();


	void set_start (const Vamos_Geometry::Three_Vector& start_corrds, 
                    double start_distance,
                    double start_angle, 
                    double start_bank,
                    const std::vector <double>& texture_offsets);

    void set_braking_marker(Braking_Marker* marker);
	Vamos_Geometry::Three_Vector next_vertex (int strip);

	void build ();
	void draw () const;

	void add_model_info (const Model_Info& info);
	

	std::vector <double> texture_offsets () const { return m_texture_offsets; }


	double min_x () const { return m_min_x; }
	double max_x () const { return m_max_x; }
	double min_y () const { return m_min_y; }
	double max_y () const { return m_max_y; }
  };
}

#endif // not _GL_ROAD_SEGMENT_H_
