// ************************************************************************* //
//                            avtFluentFileFormat.h                           //
// ************************************************************************* //

#ifndef AVT_Fluent_FILE_FORMAT_H
#define AVT_Fluent_FILE_FORMAT_H
#include <avtSTMDFileFormat.h>
#include <map>
#include <string>
#include <vector>

// Fluent plugin
#include <cstdlib>
#include <sstream>
#include <visitstream.h>

#include "vtkConvexPointSet.h"
#include "vtkDoubleArray.h"
#include "vtkHexahedron.h"
#include "vtkPoints.h"
#include "vtkPyramid.h"
#include "vtkQuad.h"
#include "vtkTetra.h"
#include "vtkTriangle.h"
#include "vtkUnstructuredGrid.h"
#include "vtkWedge.h"

using namespace std;

// ****************************************************************************
//  Class: avtFluentFileFormat
//
//  Purpose:
//      Reads in Fluent files as a plugin to VisIt.
//
//  Programmer: bdotson -- generated by xml2avt
//  Creation:   Fri Jun 30 15:02:33 PST 2006
//
//  Modifications:
//
//    Hank Childs, Fri Sep  8 14:30:04 PDT 2006
//    Added methods HasInvariantMetaData and HasInvariantSIL on the advice
//    of Terry Jordan.
//
// ****************************************************************************

class avtFluentFileFormat : public avtSTMDFileFormat
{
public:
  avtFluentFileFormat(const char*);
  virtual ~avtFluentFileFormat() { ; };

  virtual const char* GetType(void) { return "Fluent"; };
  virtual void FreeUpResources(void);

  virtual vtkDataSet* GetMesh(int, const char*);
  virtual vtkDataArray* GetVar(int, const char*);
  virtual vtkDataArray* GetVectorVar(int, const char*);

  // Number of variables is dynamic
  virtual bool HasInvariantMetaData(void) const { return false; };
  // Number of Domains is dynamic
  virtual bool HasInvariantSIL(void) const { return false; };

protected:
  virtual void PopulateDatabaseMetaData(avtDatabaseMetaData*);
  int OpenCaseFile(const char* filename);
  int OpenDataFile(const char* filename);
  int GetCaseChunk();
  void GetNumberOfCellZones();
  int GetCaseIndex();
  void LoadVariableNames();
  int GetDataIndex();
  int GetDataChunk();

  void ParseCaseFile();
  int GetDimension();
  void GetLittleEndianFlag();
  void GetNodesAscii();
  void GetNodesSinglePrecision();
  void GetNodesDoublePrecision();
  void GetCellsAscii();
  void GetCellsBinary();
  void GetFacesAscii();
  void GetFacesBinary();
  void GetPeriodicShadowFacesAscii();
  void GetPeriodicShadowFacesBinary();
  void GetCellTreeAscii();
  void GetCellTreeBinary();
  void GetFaceTreeAscii();
  void GetFaceTreeBinary();
  void GetInterfaceFaceParentsAscii();
  void GetInterfaceFaceParentsBinary();
  void GetNonconformalGridInterfaceFaceInformationAscii();
  void GetNonconformalGridInterfaceFaceInformationBinary();
  void CleanCells();
  void PopulateCellNodes();
  int GetCaseBufferInt(int ptr);
  float GetCaseBufferFloat(int ptr);
  double GetCaseBufferDouble(int ptr);
  void PopulateTriangleCell(int i);
  void PopulateTetraCell(int i);
  void PopulateQuadCell(int i);
  void PopulateHexahedronCell(int i);
  void PopulatePyramidCell(int i);
  void PopulateWedgeCell(int i);
  void PopulatePolyhedronCell(int i);
  void ParseDataFile();
  int GetDataBufferInt(int ptr);
  float GetDataBufferFloat(int ptr);
  double GetDataBufferDouble(int ptr);
  void GetData(int dataType);

  //
  //  Variables
  //

  ifstream FluentCaseFile;
  ifstream FluentDataFile;
  string CaseBuffer;
  string DataBuffer;

  vtkPoints* Points;
  vtkTriangle* Triangle;
  vtkTetra* Tetra;
  vtkQuad* Quad;
  vtkHexahedron* Hexahedron;
  vtkPyramid* Pyramid;
  vtkWedge* Wedge;
  vtkConvexPointSet* ConvexPointSet;

  struct Cell
  {
    int type;
    int zone;
    vector<int> faces;
    int parent;
    int child;
    vector<int> nodes;
  };

  struct Face
  {
    int type;
    int zone;
    vector<int> nodes;
    int c0;
    int c1;
    int periodicShadow;
    int parent;
    int child;
    int interfaceFaceParent;
    int interfaceFaceChild;
    int ncgParent;
    int ncgChild;
  };

  struct ScalarDataChunk
  {
    int subsectionId;
    int zoneId;
    vector<double> scalarData;
  };

  struct VectorDataChunk
  {
    int subsectionId;
    int zoneId;
    vector<double> iComponentData;
    vector<double> jComponentData;
    vector<double> kComponentData;
  };

  vector<Cell> Cells;
  vector<Face> Faces;
  map<int, string> VariableNames;
  vector<int> CellZones;
  vector<ScalarDataChunk> ScalarDataChunks;
  vector<VectorDataChunk> VectorDataChunks;

  vector<vector<int>> SubSectionZones;
  vector<int> SubSectionIds;
  vector<int> SubSectionSize;

  vector<string> ScalarVariableNames;
  vector<int> ScalarSubSectionIds;
  vector<string> VectorVariableNames;
  vector<int> VectorSubSectionIds;

  int LittleEndianFlag;
  int GridDimension;
  int DataPass;
  int NumberOfScalars;
  int NumberOfVectors;
};

#endif
