/*=========================================================================

  Program:   ParaView
  Module:    vtkH5PartReader.h

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*=========================================================================

  Project                 : vtkCSCS
  Module                  : vtkH5PartReader.h
  Revision of last commit : $Rev: 754 $
  Author of last commit   : $Author: utkarsh $
  Date of last commit     : $Date: 2009-10-01 17:55:30 $

  Copyright (C) CSCS - Swiss National Supercomputing Centre.
  You may use modify and and distribute this code freely providing
  1) This copyright notice appears on all copies of source code
  2) An acknowledgment appears with any substantial usage of the code
  3) If this code is contributed to any other open source project, it
  must not be reformatted such that the indentation, bracketing or
  overall style is modified significantly.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

=========================================================================*/
// .NAME vtkH5PartReader - Write H5Part (HDF5) Particle files
// .SECTION Description
// vtkH5PartReader reads compatible with H5Part : documented here
// http://amas.web.psi.ch/docs/H5Part-doc/h5part.html
// .SECTION Thanks
// John Bidiscombe of
// CSCS - Swiss National Supercomputing Centre for creating and contributing
// this class.

#ifndef vtkH5PartReader_h
#define vtkH5PartReader_h

#include "vtkPVConfig.h" // For PARAVIEW_USE_MPI
#include "vtkPolyDataAlgorithm.h"
#include <string>
#include <vector>

class vtkDataArraySelection;
class vtkMultiProcessController;

struct H5PartFile;

class vtkH5PartReader : public vtkPolyDataAlgorithm
{
public:
  static vtkH5PartReader* New();
  vtkTypeMacro(vtkH5PartReader, vtkPolyDataAlgorithm);
  void PrintSelf(ostream& os, vtkIndent indent);

  // Description:
  // Specify file name.
  void SetFileName(char* filename);
  vtkGetStringMacro(FileName);

  // Description:
  // Set/Get the array that will be used for the X coordinates
  vtkGetStringMacro(Xarray);
  vtkSetStringMacro(Xarray);

  // Description:
  // Set/Get the array that will be used for the Y coordinates
  vtkGetStringMacro(Yarray);
  vtkSetStringMacro(Yarray);

  // Description:
  // Set/Get the array that will be used for the Z coordinates
  vtkGetStringMacro(Zarray);
  vtkSetStringMacro(Zarray);

  // Description:
  // Set/Get the timestep to be read
  vtkSetMacro(TimeStep, int);
  vtkGetMacro(TimeStep, int);

  // Description:
  // Get the number of timesteps in the file
  vtkGetMacro(NumberOfTimeSteps, int);

  // Description:
  // When set (default no), the reader will generate a vertex cell
  // for each point/particle read. When using the points directly
  // this is unnecessary and time can be saved by omitting cell generation
  // vtkPointSpriteMapper does not require them.
  // When using ParaView, cell generation is recommended, without them
  // many filter operations are unavailable
  vtkSetMacro(GenerateVertexCells, int);
  vtkGetMacro(GenerateVertexCells, int);
  vtkBooleanMacro(GenerateVertexCells, int);

  // Description:
  // When this option is set, scalar fields with names which form a pattern
  // of the form scalar_0, scalar_1, scalar_2 will be combined into a single
  // vector field with N components
  vtkSetMacro(CombineVectorComponents, int);
  vtkGetMacro(CombineVectorComponents, int);
  vtkBooleanMacro(CombineVectorComponents, int);

  // Description:
  // Normally, a request for data at time t=x, where x is either before the start of
  // time for the data, or after the end, will result in the first or last
  // timestep of data to be retrieved (time is clamped to max/min values).
  // Forsome applications/animations, it may be desirable to not display data
  // for invalid times. When MaskOutOfTimeRangeOutput is set to ON, the reader
  // will return an empty dataset for out of range requests. This helps
  // avoid corruption of animations.
  vtkSetMacro(MaskOutOfTimeRangeOutput, int);
  vtkGetMacro(MaskOutOfTimeRangeOutput, int);
  vtkBooleanMacro(MaskOutOfTimeRangeOutput, int);

  bool HasStep(int Step);

  // Description:
  // An H5Part file may contain multiple arrays
  // a GUI (eg Paraview) can provide a mechanism for selecting which data arrays
  // are to be read from the file. The PointArray variables and members can
  // be used to query the names and number of arrays available
  // and set the status (on/off) for each array, thereby controlling which
  // should be read from the file. Paraview queries these point arrays after
  // the (update) information part of the pipeline has been updated, and before the
  // (update) data part is updated.
  int GetNumberOfPointArrays();
  const char* GetPointArrayName(int index);
  int GetPointArrayStatus(const char* name);
  void SetPointArrayStatus(const char* name, int status);
  void DisableAll();
  void EnableAll();
  void Disable(const char* name);
  void Enable(const char* name);
  //
  int GetNumberOfPointArrayStatusArrays() { return GetNumberOfPointArrays(); }
  const char* GetPointArrayStatusArrayName(int index) { return GetPointArrayName(index); }
  int GetPointArrayStatusArrayStatus(const char* name) { return GetPointArrayStatus(name); }
  void SetPointArrayStatusArrayStatus(const char* name, int status)
  {
    SetPointArrayStatus(name, status);
  }

  int GetNumberOfCoordinateArrays() { return GetNumberOfPointArrays(); }
  const char* GetCoordinateArrayName(int index) { return GetPointArrayName(index); }
  int GetCoordinateArrayStatus(const char* name);
  void SetCoordinateArrayStatus(const char* name, int status);

#ifdef PARAVIEW_USE_MPI

  // Description:
  // Set/Get the controller use in compositing (set to
  // the global controller by default)
  // If not using the default, this must be called before any
  // other methods.
  virtual void SetController(vtkMultiProcessController* controller);
  vtkGetObjectMacro(Controller, vtkMultiProcessController);

#endif

protected:
  vtkH5PartReader();
  ~vtkH5PartReader();
  //
  int RequestInformation(vtkInformation*, vtkInformationVector**, vtkInformationVector*);
  int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*);
  int OpenFile();
  void CloseFile();
  //  void  CopyIntoCoords(int offset, vtkDataArray *source, vtkDataArray *dest);
  // returns 0 if no, returns 1,2,3,45 etc for the first, second...
  // example : if CombineVectorComponents is true, then
  // velocity_0 returns 1, velocity_1 returns 2 etc
  // if CombineVectorComponents is false, then
  // velocity_0 returns 0, velocity_1 returns 0 etc
  int IndexOfVectorComponent(const char* name);

  std::string NameOfVectorComponent(const char* name);

  //
  // Internal Variables
  //
  char* FileName;
  int NumberOfTimeSteps;
  int TimeStep;
  int ActualTimeStep;
  double TimeStepTolerance;
  int CombineVectorComponents;
  int GenerateVertexCells;
  H5PartFile* H5FileId;
  vtkTimeStamp FileModifiedTime;
  vtkTimeStamp FileOpenedTime;
  int UpdatePiece;
  int UpdateNumPieces;
  int MaskOutOfTimeRangeOutput;
  int TimeOutOfRange;
  //
  char* Xarray;
  char* Yarray;
  char* Zarray;

  std::vector<double> TimeStepValues;
  typedef std::vector<std::string> stringlist;
  std::vector<stringlist> FieldArrays;

  // To allow paraview gui to enable/disable scalar reading
  vtkDataArraySelection* PointDataArraySelection;

  // To allow paraview gui to enable/disable scalar reading
  vtkDataArraySelection* CoordinateSelection;

#ifdef PARAVIEW_USE_MPI

  vtkMultiProcessController* Controller;

#endif

private:
  vtkH5PartReader(const vtkH5PartReader&) VTK_DELETE_FUNCTION;
  void operator=(const vtkH5PartReader&) VTK_DELETE_FUNCTION;
};

#endif
