////////////////////////////////////////////////////////////////
//
// world.h
// Copyright (c) 2002 by Wesley H. Huang.  All rights reserved.
// 
////////////////////////////////////////////////////////////////
#ifndef WORLD_H
#define WORLD_H

#include "drawable.h"
#include "cgaldefs.h"
#include <list>
#include <vector>

////////////////////////////////////////////////////////////////
//
// Obstacle class
//
////////////////////////////////////////////////////////////////
class Obstacle : public drawableObject {
  // default drawing attributes for all obstacles
  static bool defaultDrawBorder;
  static bool defaultClosed;
  static int defaultWidth;
  static bool defaultFill;
  static string defaultLineColor, defaultBodyColor;

  bool useDefaults; // use the defaults or the values for a specific object?
  Polygon shape;

public:
  const string name;

  Obstacle(const string& n, const Polygon& p);
  int numPoints() const { return shape.size();}
  void getPoint(int i, double *x, double *y) const;

  const Polygon& getShape() const { return shape;}

  void setLineColor(const char* c);
  void setBodyColor(const char* c);

  // override the functions in the base class so that we can refer to
  // the default drawing properties for Obstacles
  // 
  // These are the functions that the Graphics module will call to get
  // the properties of this object.  Use the functions above to change
  // colors.
  bool drawBorder() const;
  bool closed() const;
  float width() const;
  bool fill() const;
  const string& lineColor() const;
  const string& bodyColor() const;
};

////////////////////////////////////////////////////////////////
//
// WorldBoundary class
//
////////////////////////////////////////////////////////////////
class WorldBoundary : public drawableObject {
  Polygon shape;

public:
  WorldBoundary(Polygon& p);
  int numPoints() const  { return shape.size();}
  void getPoint(int i, double *x, double *y) const;

  const Polygon& getShape() const { return shape;}
};

////////////////////////////////////////////////////////////////
//
// World class
//
////////////////////////////////////////////////////////////////
class World {
  Bbox bb;
public:
  string name;
  WorldBoundary *boundary;
  list<Obstacle*> obstacles;

  World(const char* fname, bool verbose=false);  // read in a world from a file

  // return information on the bounding box
  double minX() const { return bb.xmin();}
  double maxX() const { return bb.xmax();}
  double minY() const { return bb.ymin();}
  double maxY() const { return bb.ymax();}
  const Bbox& getBbox() const { return bb;}
};
 
////////////////////////////////////////////////////////////////
//
// Robot class
//
////////////////////////////////////////////////////////////////
class Robot : public drawableObject {
  string name;
  Polygon shape;
  double Xpos, Ypos, Ang;

public:
  Robot(const char* fname, bool verbose=false,  // read in a robot from a file
	double x=0.0, double y=0.0, double ang=0.0);

  // set the configuration of the robot (for drawing it on the screen)
  void setConfig(double x, double y, double ang) { Xpos=x; Ypos=y; Ang=ang;}
  void getConfig(double *x, double *y, double *ang) { 
    *x=Xpos; *y=Ypos; *ang=Ang;
  }
  // the robot boundary points are returned relative to its configuration
  int numPoints() const { return shape.size();}
  void getPoint(int i, double *x, double *y) const;

  // this returns the robot's shape with respect to its local coordinate frame
  const Polygon& getShape() const { return shape;}

  void setLineColor(const char* c) { _lineColor = string(c);}
  void setBodyColor(const char* c) { _bodyColor = string(c);}

};

////////////////////////////////////////////////////////////////
//
// Location class (for representing locations as points)
//
////////////////////////////////////////////////////////////////
class Location : public drawableObject {
 public:
  // defaults
  static float defSize;
  static string defColor;

  Point p;

  Location(double x, double y, float size=0.0, const char* color=0);
  Location(const Point& pt, float size=0.0, const char* color=0);

  int numPoints() const { return 1;}
  void getPoint(int i, double *x, double *y) const {
    *x = p.x();
    *y = p.y();
  }
  void setColor(const char* c) { _lineColor = string(c);}
};


////////////////////////////////////////////////////////////////
//
// Path class
//
////////////////////////////////////////////////////////////////
class Path : public drawableObject {
 public:
  vector<Point> pts;

  Path() {
    _drawBorder = true;
    _width = 3.0;
    _lineColor = string("yellow");
    _closed = false;
    _fill = false;
    _type = drawableObject::polygon;
  }
  
  int numPoints() const { return pts.size();}
  void getPoint(int i, double *x, double *y) const {
    *x = pts[i].x();
    *y = pts[i].y();
  }
  void setColor(const char* c) { _lineColor = string(c);}
};


#endif
