#include "GR_config.h"
#include <stdio.h>
#include <stdlib.h>
#include "GR_misc.h"
#include "GR_VarArrayBase.h"
#define TOPO_DIM 2
#define SPACE_DIM 2
#include "GR_Mesh2D.h"
void vReadFile_Mesh2D(
                       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];
  char strTemp[1024];
  snprintf(strTemp, 1024, "vtk");
  char *pcWhere = strstr(strBaseFileName, strTemp);
  if (pcWhere) {
    sprintf(strFileName, "%s", strBaseFileName);
  } else {
    sprintf(strFileName, "%s.vtk", strBaseFileName);
  }

  /*newfile vtk*/
  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",
                "2d mesh input");

  /*"# vtk DataFile Version" discard_float */
  fscanf(pFInFile, "# vtk DataFile Version %*f\n");
  /*discard_line */
  fscanf(pFInFile, "%*[^\n]\n");
  /*ASCII*/
  fscanf(pFInFile, "ASCII\n");
  /*DATASET UNSTRUCTURED_GRID*/
  fscanf(pFInFile, "DATASET UNSTRUCTURED_GRID\n");
  /*POINTS nverts float*/
  fscanf(pFInFile, "POINTS %d float\n", &iNumVerts);

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

  /*"CELLS" ncells discard_integer */
  fscanf(pFInFile, "CELLS %d %*d\n", &iNumCells);
  if (iNumCells == 0)
    vFatalError("Tried to read cell data without specifying number of cells",
                "2d mesh input");
  /* Allocate both the cell-vert and cell-face arrays if they haven't been.
     One or both may have to be deleted later. */
  if (! a2iCellVert) 
    a2iCellVert = new int[iNumCells][TOPO_DIM+1];
  if (! a2iCellFace) 
    a2iCellFace = new int[iNumCells][TOPO_DIM+1];
  if (! aiCellRegion) 
    aiCellRegion = new int[iNumCells];
  if (iNumVerts == 0)
    vWarning("Number of verts unknown while reading cells; sanity checking may be crippled.");
  if (iNumFaces == 0)
    vWarning("Number of faces unknown while reading cells; sanity checking may be crippled.");
  for (int iC = 0; iC < iNumCells; iC++) {
    int iRealCell = iC;
    int iFaceA = iNumFaces, iFaceB = iNumFaces;
    int iFaceC = iNumFaces;
    int iVertA = -1, iVertB = -1, iVertC = -1;
    int iReg = 0;
    /*cells: 3 verts*/
    fscanf(pFInFile, "3 %d%d%d\n", &iVertA, &iVertB, &iVertC);
    /* Dummy line to prevent compiler complaints. */
    iReg++;
    /* The following (possibly) extra work happens to get rid */
    /* of compiler complaints about unused variables. */
    /* Remove offset from the vertex indices */
    iVertA -= iVertOffset;
    iVertB -= iVertOffset;
    iVertC -= iVertOffset;
    if ( iVertA < 0 || iVertB < 0 || iVertC < 0 ||
         ((iNumVerts > 0) && 
          (iVertA >= iNumVerts || 
           iVertB >= iNumVerts || 
           iVertC >= iNumVerts) ) ) 
      vFatalError("Vertex index out of range",
                "2d mesh input");
    (a2iCellVert)[iRealCell][0] = iVertA;
    (a2iCellVert)[iRealCell][1] = iVertB;
    (a2iCellVert)[iRealCell][2] = iVertC;

    /* The following (possibly) extra work happens to get rid */
    /* of compiler complaints about unused variables. */
    /* Remove offset from the face indices */
    iFaceA -= iFaceOffset;
    iFaceB -= iFaceOffset;
    iFaceC -= iFaceOffset;
  }

  qCellVert = true;
  /*CELL_TYPES ncells*/
  fscanf(pFInFile, "CELL_TYPES %d\n", &iNumCells);
  if (iNumCells == 0)
    vFatalError("Tried to read cell data without specifying number of cells",
                "2d mesh input");
  /* Allocate both the cell-vert and cell-face arrays if they haven't been.
     One or both may have to be deleted later. */
  if (! a2iCellVert) 
    a2iCellVert = new int[iNumCells][TOPO_DIM+1];
  if (! a2iCellFace) 
    a2iCellFace = new int[iNumCells][TOPO_DIM+1];
  if (! aiCellRegion) 
    aiCellRegion = new int[iNumCells];
  if (iNumVerts == 0)
    vWarning("Number of verts unknown while reading cells; sanity checking may be crippled.");
  if (iNumFaces == 0)
    vWarning("Number of faces unknown while reading cells; sanity checking may be crippled.");
  for (int iC = 0; iC < iNumCells; iC++) {
    int iRealCell = iC;
    int iFaceA = iNumFaces, iFaceB = iNumFaces;
    int iFaceC = iNumFaces;
    int iVertA = -1, iVertB = -1, iVertC = -1;
    int iReg = 0;
    /*cells: 5*/
    fscanf(pFInFile, "5\n");
    /* Dummy line to prevent compiler complaints. */
    iReg++;
    /* The following (possibly) extra work happens to get rid */
    /* of compiler complaints about unused variables. */
    /* Remove offset from the vertex indices */
    iVertA -= iVertOffset;
    iVertB -= iVertOffset;
    iVertC -= iVertOffset;
    /* The following (possibly) extra work happens to get rid */
    /* of compiler complaints about unused variables. */
    /* Remove offset from the face indices */
    iFaceA -= iFaceOffset;
    iFaceB -= iFaceOffset;
    iFaceC -= iFaceOffset;
  }

  /* 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);
}
