////////////////////////////////////////////////////////////////
//
// world.cc
// Copyright (c) 2002 by Wesley H. Huang.  All rights reserved.
// 
////////////////////////////////////////////////////////////////
#include "world.h"
#include "cgaldefs.h"
#include "utilities.h"
#include <fstream>
#include <math.h>



////////////////////////////////////////////////////////////////
//
// World class constructor (read in world from a file)
//
////////////////////////////////////////////////////////////////
World::World(const char* fname, bool verbose)
{
  const int bsize = 100;
  char buf[bsize];
  Polygon p;

  if (verbose)
    cout << endl << "Opening World file \"" << fname << "\"..." << endl;
  std::ifstream inpFile(fname);
  CGAL::set_ascii_mode(inpFile);

  if (verbose) cout << "Looking for the name of the world..." << endl;
  skipComments(inpFile);
  inpFile.getline(buf,bsize-1);
  name= string(buf);
  if (verbose) cout << "This world is called \"" << name << "\"" << endl;
  
  skipComments(inpFile);
  if (verbose) cout << "Reading the world boundary..." << endl;
  inpFile >> p;		// read the world boundary
  boundary = new WorldBoundary(p);
  bb = p.bbox();	// find the bounding box

  // read in the obstacles
  if (verbose) cout << "Now reading in the obstacles..." << endl;
  while (true) {
    skipComments(inpFile);
    if (inpFile.eof()) break;
    string n;
    inpFile >> n;
    if (verbose) cout << "Found the obstacle \"" << n << "\"" << endl;

    if (verbose) cout << "Reading the obstacle shape..." << endl;
    skipComments(inpFile);
    inpFile >> p;
    obstacles.push_back(new Obstacle(n,p));
    if (verbose) cout << "Done.  Looking for the next obstacle..." << endl;
  }
  if (verbose) cout << "End of file reached." << endl;
}

////////////////////////////////////////////////////////////////
//
// Obstacle class functions
//
////////////////////////////////////////////////////////////////

// default drawing attributes for obstacles
bool Obstacle::defaultDrawBorder = true;
bool Obstacle::defaultClosed     = true;
int Obstacle::defaultWidth       = 3;
bool Obstacle::defaultFill       = true;
string Obstacle::defaultLineColor("black");
string Obstacle::defaultBodyColor("red");

Obstacle::Obstacle(const string& n, const Polygon& p) : name(n)
{
  useDefaults = true;
  shape = p;
  _type = drawableObject::polygon;

  // initialize this object's drawing values to the defaults
  _drawBorder = defaultDrawBorder;
  _closed = defaultClosed;
  _width = defaultWidth;
  _fill = defaultFill;
  _lineColor = defaultLineColor;
  _bodyColor = defaultBodyColor;
}

// methods for the Obstacle class to refer to default drawing attributes
// 
bool Obstacle::drawBorder() const 
{ 
  if (useDefaults) 
    return defaultDrawBorder;
  else
    return _drawBorder;
}

bool Obstacle::closed() const
{ 
  if (useDefaults) 
    return defaultClosed;
  else
    return _closed;
}

float Obstacle::width() const 
{ 
  if (useDefaults) 
    return defaultWidth;
  else
    return _width;
}
  
bool Obstacle::fill() const
{
  if (useDefaults)
    return defaultFill;
  else
    return _fill;
}

const string& Obstacle::lineColor() const
{
  if (useDefaults)
    return defaultLineColor;
  else
    return _lineColor;
}

const string& Obstacle::bodyColor() const
{
  if (useDefaults)
    return defaultBodyColor;
  else
    return _bodyColor;
}

void Obstacle::setLineColor(const char* c)
{
  useDefaults = false;
  _lineColor = string(c);
}

void Obstacle::setBodyColor(const char* c)
{
  useDefaults = false;
  _bodyColor = string(c);
}

void Obstacle::getPoint(int i, double *x, double *y) const
{ 
  *x = shape.vertex(i).x();
  *y = shape.vertex(i).y();
}


////////////////////////////////////////////////////////////////
//
//  WorldBoundary class
//
////////////////////////////////////////////////////////////////

WorldBoundary::WorldBoundary(Polygon& p) 
{
  shape = p;
  _type = drawableObject::polygon;

  // define how the boundary should be drawn
  _drawBorder = true;
  _closed = true;
  _width = 3;
  _fill = false;
  _lineColor = "blue";
  _bodyColor = "";
}

void WorldBoundary::getPoint(int i, double *x, double *y) const
{ 
  *x = shape.vertex(i).x();
  *y = shape.vertex(i).y();
}


////////////////////////////////////////////////////////////////
//
// Robot class functions
//
////////////////////////////////////////////////////////////////
Robot::Robot(const char* fname, bool verbose, 
	     double x, double y, double ang) 
{
  const int bsize = 100;
  char buf[bsize];
  
  if (verbose)
    cout << endl << "Opening Robot file \"" << fname << "\"..." << endl;
  std::ifstream inpFile(fname);
  CGAL::set_ascii_mode(inpFile);

  if (verbose) cout << "Looking for the name of the robot..." << endl;
  skipComments(inpFile);
  inpFile.getline(buf,bsize-1);
  name= string(buf);
  if (verbose) cout << "This robot is called \"" << name << "\"" << endl;
  
  skipComments(inpFile);
  if (verbose) cout << "Reading the robot boundary..." << endl;
  inpFile >> shape;
  _type = drawableObject::polygon;

  Xpos = x;
  Ypos = y;
  Ang = ang;

  _drawBorder = true;
  _closed = true;
  _width = 2;
  _fill = true;
  _lineColor = string("black");
  _bodyColor = string("blue");
}

void Robot::getPoint(int i, double *x, double *y) const
{ 
  *x = Xpos + shape.vertex(i).x()*cos(Ang) - shape.vertex(i).y()*sin(Ang);
  *y = Ypos + shape.vertex(i).x()*sin(Ang) + shape.vertex(i).y()*cos(Ang);
}

////////////////////////////////////////////////////////////////
//
// Location class functions
//
////////////////////////////////////////////////////////////////

float Location::defSize = 5.0;
string Location::defColor = string("yellow");

Location::Location(double x, double y, float size, const char* color) : p(x,y) 
{
  _type = drawableObject::polygon;

  if (size == 0.0)
    _width = defSize;
  else
    _width = size;
  
  if (color == 0)
    _lineColor = defColor;
  else
    _lineColor = string(color);
}

Location::Location(const Point& pt, float size, const char* color) 
  : p(pt) 
{
  _type = drawableObject::polygon;

  if (size == 0.0)
    _width = defSize;
  else
    _width = size;

  if (color == 0)
    _lineColor = defColor;
  else
    _lineColor = string(color);
}

