#include "GR_config.h"
#include <stdio.h>
#include <stdlib.h>
#include "GR_misc.h"
#include "GR_VarArrayBase.h"
#define TOPO_DIM 3
#define SPACE_DIM 3
#include "GR_VolMesh.h"
void vReadFile_VolMesh(
                       const char * const strBaseFileName,
                       int& iNumVerts,
                       int& iNumFaces,
                       int& iNumCells,
                       int& iNumBdryFaces,
                       int& iNumIntBdryFaces,
                       bool& qFaceVert,
                       bool& qCellVert,
                       bool& qFaceCell,
                       bool& qCellFace,
                       bool& qCellRegion,
                       bool& qBFaceFace,
                       bool& qBFaceVert,
                       bool& qBFaceBC,
                       bool& qIntBFaceFace,
                       bool& qIntBFaceVert,
                       bool& qIntBFaceBC,
                       VAVertex& VAVerts,
                       int (*&a2iFaceVert)[TOPO_DIM],
                       int (*&a2iFaceCell)[2],
                       int (*&a2iCellVert)[TOPO_DIM+1],
                       int (*&a2iCellFace)[TOPO_DIM+1],
                       int *&aiCellRegion,
                       int *&aiBFaceFace,
                       int *&aiBFaceBC,
                       int (*&a2iBFaceVert)[TOPO_DIM],
                       int (*&a2iIntBFaceFace)[2],
                       int *&aiIntBFaceBC,
                       int (*&a2iIntBFaceVert)[TOPO_DIM]
                       )
{
  iNumVerts = 0;
  iNumFaces = 0;
  iNumCells = 0;
  iNumIntBdryFaces = 0;
  iNumBdryFaces = 0;
  qFaceVert = false;
  qCellVert = false;
  qFaceCell = false;
  qCellFace = false;
  qCellRegion = false;
  a2iFaceCell = reinterpret_cast<int(*)[2]> (NULL);
  a2iFaceVert = reinterpret_cast<int(*)[TOPO_DIM]> (NULL);
  a2iCellVert = reinterpret_cast<int(*)[TOPO_DIM+1]> (NULL);
  a2iCellFace = reinterpret_cast<int(*)[TOPO_DIM+1]> (NULL);
  aiCellRegion = reinterpret_cast<int *> (NULL);
  qBFaceVert = false;
  qBFaceFace = false;
  qBFaceBC = false;
  aiBFaceFace = reinterpret_cast<int *> (NULL);
  aiBFaceBC   = reinterpret_cast<int *> (NULL);
  a2iBFaceVert= reinterpret_cast<int(*)[TOPO_DIM]> (NULL);
  qIntBFaceFace = false;
  qIntBFaceVert = false;
  qIntBFaceBC   = false;
  a2iIntBFaceFace = reinterpret_cast<int(*)[2]> (NULL);
  aiIntBFaceBC    = reinterpret_cast<int *> (NULL);
  a2iIntBFaceVert = reinterpret_cast<int(*)[TOPO_DIM]> (NULL);
 
  int iVertOffset = 0, iFaceOffset = 0;
  int iCellOffset = 0, iBFaceOffset = 1;
  FILE *pFInFile = fopen("/dev/zero", "r");
  char strFileName[1024];
  sprintf(strFileName, "%s.vmesh", strBaseFileName);

  /*newfile vmesh*/
  printf("Opening input file %s\n", strFileName);
  if (pFInFile) fclose(pFInFile);
  pFInFile = fopen(strFileName, "r");
  if (NULL == pFInFile)
    vFatalError("Couldn't open input file for reading",
                "3d mesh input");

  /*ncells nfaces nbfaces nverts*/
  fscanf(pFInFile, "%d %d %d %d\n", &iNumCells, &iNumFaces, &iNumBdryFaces, &iNumVerts);

  if (iNumVerts == 0)
    vFatalError("Tried to read vertex data without specifying number of vertices",
                "3d mesh input");
  VAVerts.vSetup(iNumVerts);
  for (int iV = 0; iV < iNumVerts; iV++) {
    int iRealVert = iV;
    double dXX, dYY;
    double dZZ;
    /*verts: coords*/
    fscanf(pFInFile, "%lf%lf%lf\n", &dXX, &dYY, &dZZ);
    {
      double adCoord[] = {dXX, dYY, dZZ};
      (VAVerts.pTEntry(iRealVert))->vSetCoords(SPACE_DIM, adCoord);
    }
  }


  if (iNumFaces == 0)
    vFatalError("Tried to read face data without specifying number of faces",
                "3d mesh input");
  /* Allocate both the face-vert and face-cell arrays if they haven't been.
     One or both may have to be deleted later. */
  if (! a2iFaceVert)
    a2iFaceVert = new int[iNumFaces][TOPO_DIM];
  if (! a2iFaceCell)
    a2iFaceCell = new int[iNumFaces][2];
  if (iNumVerts == 0)
    vWarning("Number of verts unknown while reading faces; sanity checking may be crippled.");
  if (iNumCells == 0)
    vWarning("Number of cells unknown while reading faces; sanity checking may be crippled.");
  for (int iF = 0; iF < iNumFaces; iF++) {
    int iRealFace = iF;
    int iCellA = iNumCells, iCellB = iNumCells;
    int iVertA = -1, iVertB = -1;
    int iVertC = -1;
    /*faces: cells verts*/
    fscanf(pFInFile, "%d%d %d%d%d\n", &iCellA, &iCellB, &iVertA, &iVertB, &iVertC);
    /* Remove an offset from the vertex indices if needed. */
    iVertA -= iVertOffset;
    iVertB -= iVertOffset;
    iVertC -= iVertOffset;
    if ( iVertA < 0 || iVertB < 0 ||
         iVertC < 0 || 
         ((iNumVerts > 0) && 
          (iVertA >= iNumVerts || 
           iVertC >= iNumVerts || 
           iVertB >= iNumVerts) ) ) 
      vFatalError("Vertex index out of range",
                "3d mesh input");
    (a2iFaceVert)[iRealFace][0] = iVertA;
    (a2iFaceVert)[iRealFace][1] = iVertB;
    (a2iFaceVert)[iRealFace][2] = iVertC;

    /* Remove an offset from the vertex indices if needed. */
    if (iCellA >= 0) iCellA -= iCellOffset;
    if (iCellB >= 0) iCellB -= iCellOffset;
    /* Can not check cell index for out-of-range low, */
    /* because BC's have a negative index. */
    if ( iNumCells > 0 && 
         (iCellA >= iNumCells || 
          iCellB >= iNumCells) ) 
      vFatalError("Cell index out of range",
                "3d mesh input");
    (a2iFaceCell)[iRealFace][0] = iCellA;
    (a2iFaceCell)[iRealFace][1] = iCellB;
  }

  qFaceVert = true;
  qFaceCell = true;

  if (iNumBdryFaces == 0)
    vFatalError("Tried to read bdry face data without specifying number of bdry faces",
                "3d mesh input");
  /* Allocate the bface-face, bface-vert, and bface-BC arrays. */
  /* One or more may have to be deleted later. */
  if (! aiBFaceFace) 
    aiBFaceFace = new int[iNumBdryFaces];
  if (! aiBFaceBC) 
    aiBFaceBC   = new int[iNumBdryFaces];
  if (! a2iBFaceVert) 
    a2iBFaceVert= new int[iNumBdryFaces][TOPO_DIM];
  if (iNumVerts == 0)
    vWarning("# of verts unknown while reading bdry faces; sanity checking may be crippled.");
  if (iNumFaces == 0)
    vWarning("# of faces unknown while reading bdry faces; sanity checking may be crippled.");
  for (int iBF = 0; iBF < iNumBdryFaces; iBF++) {
    int iRealBFace = iBF;
    int iFace = iNumFaces, iBC = -100;
    int iVertA = -1, iVertB = -1;
    int iVertC = -1;
    /*bdryfaces: face bc verts*/
    fscanf(pFInFile, "%d %d %d%d%d\n", &iFace, &iBC, &iVertA, &iVertB, &iVertC);
    /* Remove offset from the vertex indices */
    iVertA -= iVertOffset;
    iVertB -= iVertOffset;
    iVertC -= iVertOffset;
    if ( iVertA < 0 || iVertB < 0 ||
         iVertC < 0 ||
         ((iNumVerts > 0) && 
          (iVertA >= iNumVerts || 
           iVertC >= iNumVerts || 
           iVertB >= iNumVerts) ) ) 
      vFatalError("Vertex index out of range",
                "3d mesh input");
    (a2iBFaceVert)[iRealBFace][0] = iVertA;
    (a2iBFaceVert)[iRealBFace][1] = iVertB;
    (a2iBFaceVert)[iRealBFace][2] = iVertC;


    /* Remove offset from face index */ 
    iFace -= iFaceOffset;
    if ( iFace < 0 ||
         ((iNumFaces > 0) && 
          (iFace >= iNumFaces) ) ) 
      vFatalError("Face index out of range",
                "3d mesh input");
    (aiBFaceFace)[iRealBFace] = iFace;
    if ( iBC <= 0 )
      vFatalError("Boundary condition out of range",
                "3d mesh input");
    (aiBFaceBC)[iRealBFace] = iBC;
  }

  qBFaceVert = true;
  qBFaceFace = true;
  /* Get rid of the face-vert array if it isn't used. */
  if (!(qFaceVert) && a2iFaceVert) {
    delete [] a2iFaceVert;
    a2iFaceVert = reinterpret_cast<int(*)[TOPO_DIM]> (NULL);
  }

  /* Get rid of the face-cell array if it isn't used. */
  if (!(qFaceCell) && (a2iFaceCell)){
    delete [] a2iFaceCell;
    a2iFaceCell = reinterpret_cast<int(*)[2]> (NULL);
  }

  /* Get rid of the cell-vert array if it isn't used. */
  if (!(qCellVert) && (a2iCellVert)) {
    delete [] a2iCellVert;
    a2iCellVert = reinterpret_cast<int(*)[TOPO_DIM+1]> (NULL);
  }

  /* Get rid of the cell-face array if it isn't used. */
  if (!(qCellFace) && (a2iCellFace)) {
    delete [] a2iCellFace;
    a2iCellFace = reinterpret_cast<int(*)[TOPO_DIM+1]> (NULL);
  }

  /* Get rid of the cell-region array if it isn't used. */
  if (!(qCellRegion) && (aiCellRegion)) {
    delete [] aiCellRegion;
    aiCellRegion = reinterpret_cast<int *> (NULL);
  }

  /* Get rid of the bface-face array if it isn't used. */
  if (!(qBFaceFace) && (aiBFaceFace)){
    delete [] aiBFaceFace;
    aiBFaceFace = reinterpret_cast<int *> (NULL);
  }

  /* Get rid of the bface-BC array if it isn't used. */
  if (!(qBFaceBC) && (aiBFaceBC)){
    delete [] aiBFaceBC;
    aiBFaceBC = reinterpret_cast<int *> (NULL);
  }

  /* Get rid of the bface-vert array if it isn't used. */
  if (!(qBFaceVert) && (a2iBFaceVert)) {
    delete [] a2iBFaceVert;
    a2iBFaceVert = reinterpret_cast<int(*)[TOPO_DIM]> (NULL);
  }

  /* The following lines prevent compiler complaints. */
  iBFaceOffset++;
  iFaceOffset++;
  iCellOffset++;
  iVertOffset++;
  fclose(pFInFile);
}
