#ifndef GR_BFaceCV
#define GR_BFaceCV 1

#include "GR_config.h"

#include "GR_misc.h"
#include "GR_Vertex.h"

class BFaceCV
{
private:
  int iBC, iN;
  Vert **ppV;
  BFaceCV (const BFaceCV &) : iBC(), iN(), ppV(NULL) {assert (0);}
protected:
  BFaceCV & operator = (const BFaceCV & BFCV)
    {
      if (this != &BFCV)
      {
	delete[]ppV;
	iBC = BFCV.iBC;
	iN = BFCV.iN;
	ppV = new Vert *[iN];
	for (int ii = 0; ii < iN; ii++)
	{
	  ppV[ii] = BFCV.ppV[ii];
	}
      }
      return (*this);
    }
public:
  BFaceCV () : iBC(iInvalidBC), iN(0), ppV(NULL) {}
  inline BFaceCV (const int iNV, Vert ** const ppVIn, const int iBCIn);
  virtual ~ BFaceCV ()
    {
      if (ppV) {
	delete [] ppV;
	ppV = NULL;
      }
    }
// Data member reporting
  inline Vert *pVVert (const int i) const;
  int iBdryCond () const
  {
    return iBC;
  }
  inline bool qHasVert (Vert * const pV) const;
// Data setting
  inline void vSetVerts (const int iNV, Vert ** const ppVIn);
  void vSetBC (const int iBCIn)
  {
    iBC = iBCIn;
  }
  inline void vReplaceVert (Vert * const pVOld, Vert * const pVNew);
}; // End of BFaceCV declaration

#ifndef BROKEN_INLINE

inline BFaceCV::
BFaceCV (const int iNV, Vert ** const ppVIn, const
	 int iBCIn) :
  iBC(iBCIn), iN(iNV), ppV(NULL)
{
  assert (iNV >= 1 && iNV <= 4);
  ppV = new Vert *[iNV];
  if (ppVIn)
    {
      for (int i = 0; i < iNV; i++)
	{
	  if (ppVIn[i] == pVInvalidVert)
	    vFatalError ("Invalid vertex assigned to boundary face",
			 "BFaceCV constructor");
	  ppV[i] = ppVIn[i];
	}
    }
  else
    {
      for (int i = 0; i < iNV; i++)
	ppV[i] = pVInvalidVert;
    }
}

#endif

inline Vert *BFaceCV::
pVVert (const int i)
     const
     {
       assert (i >= 0 && i < iN);
       return (ppV[i]);
     }

#ifndef BROKEN_INLINE

     inline bool BFaceCV::qHasVert (Vert * const pV)
     const
     {
       assert (pV->qValid ());
       for (int i = 0; i < iN; i++)
	 if (pV == ppV[i])
	   return true;
       return false;
     }

     inline void BFaceCV::vReplaceVert (Vert * const pVOld, Vert * const pVNew)
{
  assert2 (pVOld->qValid(), "Tried to replace non-existent vert");
  assert2 (pVNew->qValid(), "Tried to add non-existent vert");
  int iRepl = -1;
  int i;
  for (i = 0; i < iN; i++)
    {
      assert2 (pVNew != ppV[i], "Vert already exists for this BFace");
      if (ppV[i] == pVOld)
	iRepl = i;
    }
  assert2 (iRepl >= 0, "Tried to replace vert which doesn't bound this BFace");
  if (i < 0)
    vFatalError ("Tried to replace vert which didn't bound face",
		 "BFace::vReplaceVert");
  ppV[iRepl] = pVNew;
}

inline void BFaceCV::
vSetVerts (const int iNV, Vert ** const ppVIn)
{
  assert (iNV >= 1 && iNV <= 4);
  if (ppV && iNV != iN)
    {
      delete[]ppV;
      ppV = new Vert *[iNV];
    }
  else if (!ppV)
    ppV = new Vert *[iNV];
  iN = iNV;
  for (int i = 0; i < iNV; i++)
    {
      if (ppVIn[i] == pVInvalidVert || !ppVIn[i]->qValid ())
	vFatalError ("Invalid vertex assigned to boundary face",
		     "BFaceCV constructor");
      ppV[i] = ppVIn[i];
    }
}

#endif

class EdgeBFaceCV:public BFaceCV
{
  public:
  EdgeBFaceCV (Vert ** const ppVIn = 0, const int iBCIn = iInvalidBC)
  : BFaceCV (2, ppVIn, iBCIn)
  {
  }
};

class TriBFaceCV:public BFaceCV
{
  public:
  TriBFaceCV (Vert ** const ppVIn = 0, const int iBCIn = iInvalidBC)
  : BFaceCV (3, ppVIn, iBCIn)
  {
  }
};

class QuadBFaceCV:public BFaceCV
{
  public:
  QuadBFaceCV (Vert ** const ppVIn = 0, const int iBCIn = iInvalidBC)
  : BFaceCV (4, ppVIn, iBCIn)
  {
  }
};

#endif
