#ifndef GRID
#define GRID
#include "Vector2.h"
#include <complex>

#include "cpplapack.h"
using namespace CPPL;


#define PI 3.1415926535897931

typedef std::complex<double> dcomplex;

class Grid
{
private:
   int size;
   Vector2 ** points;
   bool ** interiorPts;
   std::vector<dcomplex> ** Pij;
   std::vector<Vector2> polygon;
   std::vector<Vector2> movedPolygon;

   double intScale;
   bool setup;

   int nSample;
public:
   std::vector<Vector2> controlPoints;
   static const int DRAW_WIRE = 0;
   static const int DRAW_TEXTURE = 1;
   int drawStyle;
   bool drawpoly;

   Grid();
   void Resize(int n);

   void Draw();
   void AddPolygonPoint(const float & x, const float & y);
   void MovePolygonPoint(const float & x, const float & y, const float & dx, const float & dy);
   void ClearPlygon() { polygon.clear(); movedPolygon.clear(); }
   void ResetPolygon() { for (unsigned int i = 0; i < polygon.size(); ++i) movedPolygon[i] = polygon[i]; }
   void AddControlPoint(const float & x, const float & y);
   void MoveControlPoint(const float & x, const float & y, const float & dx, const float & dy);
   ~Grid(void);

   bool checkInPolygon(Vector2 pt);


   // To compute tex coords.
   Vector2 ComputeTransformedCoord(int x, int y);

   void toggleSetup() { setup = !setup; }

   // Barycentric coord functions.
   int index_wrap(int j);
   dcomplex A(int j);
   dcomplex B(dcomplex z, int j);
   dcomplex C(dcomplex z, int j);
   dcomplex D(dcomplex z, int j);
   dcomplex P(dcomplex z, int j, zgematrix* N);

   zgematrix * computeC();
   zgematrix * computel_D(double lambda);
   zgematrix * computeA(zgematrix * Cmat, zgematrix * Dmat);
   zgematrix * computeN(zgematrix * Amat);

   zgematrix * build_fullNmat();

   void precompute_all_pij();

   Vector2 getClosestPointOnLineSegment(Vector2 a, Vector2 b, Vector2 pt);

   double lambda;
};

#endif


