#ifndef GR_InsertionQueueEntry
#define GR_InsertionQueueEntry 1

#include "GR_config.h"

class InsertionQueueEntry {
public:
  enum eEntryType {eInvalid, eTetCell, eTriBFace, eSubSeg, eTriCell,
		   eBdryEdge};
  // Note that multimaps with double keys sort from smallest to largest
  // by default, so big negative values go to the the head of the queue.
  enum dPriorityValues {dSubSegPriority = INT_MIN,
			dSubSegOffsetPriority = INT_MIN / 2,
			dBdryFacePriority = INT_MIN / 4,
			dBdryFaceOffsetPriority = INT_MIN / 8,
			dWorstCellPriority = INT_MIN / 16,
			dNeverQueuedPriority = INT_MAX,
			dInvalidPriority = INT_MAX};
private:
  mutable double dPri;
  double adNewPtLoc[3];
  union {
    Cell *pC;
    BFace *pBF; // Actually derived from Cell, so unnecessary, but clearer.
  };
  Vert *apV[4];
  enum eEntryType eET;
  // Because bit-wise copy is correct for this class, the default
  // operator= and copy constructor don't need to be overridden.
public:
  InsertionQueueEntry() : dPri(dInvalidPriority), 
    pC(pCInvalidCell), eET(eInvalid)
    {
      // An obviously bogus location value...
      adNewPtLoc[0] = adNewPtLoc[1] = adNewPtLoc[2] = -1e300;
    }
  InsertionQueueEntry(Cell * const);
  InsertionQueueEntry(BFace * const);
  InsertionQueueEntry(Vert * const, Vert * const);
  double dEvaluatePriority() const;
  bool qInsertOffsetPoint() const {
    return ((dPri >= dSubSegOffsetPriority && dPri < dBdryFacePriority) ||
	    (dPri >= dBdryFaceOffsetPriority && dPri < dWorstCellPriority));
  }
  void vSetPointLocation(double adLoc[])
    {
      adNewPtLoc[0] = adLoc[0];
      adNewPtLoc[1] = adLoc[1];
      // The last component may be garbage, which is okay, but it may
      // also be illegal to read that location, which is not.
      if (eET == eTetCell || eET == eTriBFace || eET == eSubSeg)
	adNewPtLoc[2] = adLoc[2];
    }
  const double* adPointLocation() const {return adNewPtLoc;}
  Cell *pCCell() const
    {
      assert(eET == eTetCell || eET == eTriCell);
      return pC;
    }
  BFace *pBFBFace() const
    {
      assert(eET == eTriBFace || eET == eBdryEdge);
      return pBF;
    }
  Vert *pVVert(const int i) const
    {
      assert(i >= 0 && i <= 3);
      assert(((eET == eSubSeg || eET == eBdryEdge) && i <= 1) ||
	     ((eET == eTriBFace || eET == eTriCell) && i <= 2) ||
	     (eET == eTetCell));
      return (apV[i]);
    }
  enum eEntryType eType() const {return eET;}
  bool qStillInMesh() const;
  bool operator==(const InsertionQueueEntry& IQE) const;
  bool operator!=(const InsertionQueueEntry& IQE) {return (!(*this == IQE));}
};

#endif


