#ifndef GR_AnisoFront
#define GR_AnisoFront 1

#include <set>
#include <vector>
#include <queue>
#include "GR_config.h"
#include "GR_Vertex.h"
#include "GR_AnisoFrontEntry.h"
#include "GR_VarArray2D.h"

typedef std::vector<AnisoFrontEntry*> AnisoFrag;

// Instead of using a pure queue, I'm using a variable-sized array, for
// two reasons.  First, I'm not confident of my ability to create an
// AnisoFrontEntry class that would correctly survive the copy
// construction and/or operator= calls that an STL queue would use.

// Second, I don't want to pop from the queue anyway, because I'd
// lose information in old front edges (including stuff you
// need to set up connectivity).  Not sure what the right fix for
// -that- is; I don't want to have to have -all- for the front data
// around forever, especially in 3D for memory reasons.  On the other
// hand, having stale front data would make cell merging much easier.
// In the long run, I need a clever scheme to keep info as long as
// needed for these purposes but no longer.  In the end, using level
// information and popping level k - 2 before building level k will
// probably work.  Front advancement will have to use an actual
// iterator instead of simply popping off the front of the queue, but
// that's okay.  It just means that the "queue" would have to
// implemented using a multimap sorted by level, or something similar,
// instead of a true queue.

class AnisoFront {
private:
  VAAnisoFrontEntry VAAF;
  Mesh2D *pM2D;
  int iMarchFromMeetingPoint(AnisoFrontEntry * const pAFELeft,
			   AnisoFrontEntry * const pAFERight);
  int iMarchFromLeftEndPoint(AnisoFrontEntry * const pAFE);
  int iMarchFromRightEndPoint(AnisoFrontEntry * const pAFE);
  int iStartOfLayer;
  double dFinishAR;
  std::queue<AnisoFrag> queueFrag;
  std::set<Vert*> spVToDelete;
  AnisoFront(const AnisoFront&) {assert(0);}
  AnisoFront& operator=(const AnisoFront&) {assert(0); return (*this);}
public:
  AnisoFront(Mesh2D& M2D, const int iNStructBC, const int aiStructBC[]);
  ~AnisoFront() {}
  AnisoFrontEntry *pAFENewEntry() {return VAAF.pTNewEntry();}
  AnisoFrontEntry *pAFEEntry(const int i) const
    {
      assert(i >= 0 && i < iSize());
      return &VAAF[i];
    }
  void vCreateChildEntry(AnisoFrontEntry * const pAFE);
  int iSize() const {return VAAF.iSize();}
  int iAddLayer(const double dMinAR);

  void vInitFrontQueue(const double dFinishAR_In);
  void vMarchChanSteger(const int iLayers, int& iVertsAdded);

  void vRecoverEdges(std::set<Face*>& spFRecovered);
  void vCreateQuads();
};

#endif
