#ifndef GR_GRGEOM2D_H
#define GR_GRGEOM2D_H 1

/* 2D GRUMMP geometry class: */
/* Reads boundary data from a two dimensional boundary file */
/* then initializes and stores the geometry and topology accordingly. */

#include "GR_config.h"
#include "GR_misc.h"
#include "CubitString.hpp"
#include <vector>
#include <list>
#include <map>

class CubitVector;
class GRPoint;
class GRCurve;
class GRCoEdge;
class GRLoop;

class GRGeom2D {

 public:

  GRGeom2D();
  GRGeom2D(const char* const bdry_file);
  ~GRGeom2D();

  //Once the bdry data has been read in the constructor, init geometry
  //by calling this function.
  void build_geometry();

 private:

  //Member variables containing the number of points and curves.
  int n_points, n_curves, n_constructed_curves;

  //Geometric entities stored in these lists
  std::list<GRPoint*> point_list;
  std::list<GRCurve*> curve_list;
  std::list<GRCoEdge*> coedge_list;
  std::list<GRLoop*> loop_list;

  //Struct containing curve info extracted from file.
  struct curve_info {
    CubitString curve_type;
    CubitString l_cond; int left;
    CubitString r_cond; int right;
    std::vector<double> curve_data;
  };

  //Vector containing the boundary point coordinates
  std::vector<CubitVector> v_points;
  //Vector containing the string defining every curves.
  std::vector<curve_info> v_curves;
  
  ///////////////////////
  ///PARSING FUNCTIONS///
  ///////////////////////
  //Opens the boundary file and returns a point to this file.
  FILE* open_bdry_file(const char* const bdry_file) const;
  //Reads and initialized the number of points and curves.
  void read_num_entities(FILE* const f);
  //Reads the point coords and stores into a vector
  void read_points(FILE* const f);
  //Reads the curve info and stores the string into a vector
  void read_curves(FILE* const f);
  //Checks patch name validity by comparing strings
  bool valid_patch_type(const char* const str) const;
  //Special line reader similar to vGetLineOrAbort()
  void get_line(char buffer[], const int size, FILE *f) const;
  
  ////////////////////////
  ///BUILDING FUNCTIONS///
  ////////////////////////
  //Builds one curve (curve type built depends on ci.curve_type)
  void build_curve(const int curve_id, 
		   std::map<int, GRPoint*>& created_points,
		   std::map<int, std::vector<GRCoEdge*> >& region_curves);
  //Builds a vertex "curve" (a vertex embeded in a face)
  void build_vertex(const curve_info* const ci, 
		    std::map<int, GRPoint*>& created_points,
		    std::map<int, std::vector<GRCoEdge*> >& region_curves);
  //Builds a polyline (or a single line)
  void build_polyline(const curve_info* const ci, 
		      std::map<int, GRPoint*>& created_points,
		      std::map<int, std::vector<GRCoEdge*> >& region_curves);
  //Builds an arc
  void build_arc(const curve_info* const ci, 
		 std::map<int, GRPoint*>& created_points,
		 std::map<int, std::vector<GRCoEdge*> >& region_curves);
  //Builds a long arc
  void build_longarc(const curve_info* const ci, 
		     std::map<int, GRPoint*>& created_points,
		     std::map<int, std::vector<GRCoEdge*> >& region_curves);
  //Builds a circle
  void build_circle(const curve_info* const ci, 
		    std::map<int, GRPoint*>& created_points,
		    std::map<int, std::vector<GRCoEdge*> >& region_curves);
  //Builds a bezier curve
  void build_bezier(const curve_info* const ci, 
		    std::map<int, GRPoint*>& created_points,
		    std::map<int, std::vector<GRCoEdge*> >& region_curves);
  //Builds an interpolated spline
  void build_spline(const curve_info* const ci, 
		    std::map<int, GRPoint*>& created_points,
		    std::map<int, std::vector<GRCoEdge*> >& region_curves);

  //Build a co-edge given a region id.
  void build_coedge(int region, GRCurve* const curve,
		    std::map<int, std::vector<GRCoEdge*> >& region_curves);

  //Build the loops for a "surface" given the co-edges of this "surface"
  void build_loop(std::vector<GRCoEdge*>& coedge_vector, 
		  std::vector<GRLoop*>& created_loops);

  ///////////////////
  ///VERIFICATION////
  ///////////////////

  //Verifies that the regions were correctly specified in the boundary file.
  void verify_region_conditions(int region, std::vector<GRLoop*>& created_loops);

  //Function that outputs geometry info to command line (should only call if NDEBUG)
  void verification();

};

#endif
