#include "GR_Face.h"
#include "GR_BFace.h"
#include "GR_Cell.h"
#include "GR_Vec.h"

BFace& BFace::operator=(const BFace& BF)
{
  assert(eType() == BF.eType());
  assert(! BF.qDeleted());
  if (this != &BF) {
    assert(iNumFaces() == 1 || iNumFaces() == 2);
    assert(BF.iNumFaces() == iNumFaces());
    for (int i = 0; i < iNumFaces(); i++ ) {
      if ( !qDeleted() &&
	   ppFFaces[i]->qValid() &&
	   ppFFaces[i]->qHasCell(this) ) 
        ppFFaces[i]->vRemoveCell(this);
      ppFFaces[i] = BF.ppFFaces[i];
      if (ppFFaces[i]->qValid())
        ppFFaces[i]->vReplaceCell(&BF, this);
    }
    vCopyAllFlags(BF);
    qOffsetInsRequested = BF.qOffsetInsRequested;
    qNeverDoOffsetIns = BF.qNeverDoOffsetIns;
    adInsertionLoc[0] = BF.adInsertionLoc[0];
    adInsertionLoc[1] = BF.adInsertionLoc[1];
    adInsertionLoc[2] = BF.adInsertionLoc[2];
  }
  return (*this);
}

void BFace::vVecSize(double adRes[]) const
{
  assert(pFFace(0)->qValid());
  int iDim = pFFace(0)->pVVert(0)->iSpaceDimen();
  if (qDeleted()) {
    adRes[0] = adRes[1] = 0;
    if (iDim == 3) adRes[2] = 0;
    return;
  }
  Face *pF = ppFFaces[0];
  int iSign = (pF->pCCellLeft() == dynamic_cast<const Cell*>(this)) ? 1 : -1;
  pF->vNormal(adRes);
  if (iDim == 2) {
    vSCALE2D(adRes, iSign);
  }
  else {
    vSCALE3D(adRes, iSign);
  }
}

void BFace::vUnitNormal(double adRes[]) const
{
  assert(pFFace(0)->qValid());
  int iDim = pFFace(0)->pVVert(0)->iSpaceDimen();
  if (qDeleted()) {
    adRes[0] = adRes[1] = 0;
    if (iDim == 3) adRes[2] = 0;
    return;
  }
  Face *pF = ppFFaces[0];
  int iSign = (dynamic_cast<BFace*>(pF->pCCellLeft()) == this) ? 1 : -1;
  pF->vUnitNormal(adRes);
  if (iDim == 2) {
    vSCALE2D(adRes, iSign);
  }
  else {
    vSCALE3D(adRes, iSign);
  }
}

const Vert* BFace::pVVert(const int i) const
{
  assert(i >= 0 && i < iNumVerts());
  assert(dynamic_cast<BFace*>(pFFace(0)->pCCellLeft())  == this ||
         dynamic_cast<BFace*>(pFFace(0)->pCCellRight()) == this);
  bool qReverse = true;
  // Traverse the bdry face in the direction so that the face is
  // traversed in the opposite direction than it is for the interior
  // cell.
  if (eType() == eBdryEdge) qReverse = false;
  if (eType() == eIntBdryEdge) qReverse = false;
  if (dynamic_cast<BFace*>(pFFace(0)->pCCellLeft()) == this)
    qReverse = !qReverse;
  if (qReverse) 
    return (pFFace(0)->pVVert(iNumVerts() - i - 1));
  else 
    return (pFFace(0)->pVVert(i));
}

double BFace::dSize() const
{
  if (qDeleted()) return (double(0));
  else return ppFFaces[0]->dSize();
}

