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

  Program:   Visualization Toolkit
  Module:    vtkVPICReader.h

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm 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.

=========================================================================*/
/**
 * @class   vtkVPICReader
 * @brief   class for reading VPIC data files
 *
 * vtkDataReader is a helper superclass that reads the vtk data file header,
 * dataset type, and attribute data (point and cell attributes such as
 * scalars, vectors, normals, etc.) from a vtk data file.  See text for
 * the format of the various vtk file types.
 *
 * @sa
 * vtkPolyDataReader vtkStructuredPointsReader vtkStructuredGridReader
 * vtkUnstructuredGridReader vtkRectilinearGridReader
 */

#ifndef vtkVPICReader_h
#define vtkVPICReader_h

#include "vtkIOVPICModule.h" // For export macro
#include "vtkImageAlgorithm.h"

class vtkCallbackCommand;
class vtkDataArraySelection;
class vtkFloatArray;
class vtkStdString;
class vtkMultiProcessController;
class vtkInformation;

class VPICDataSet;
class GridExchange;

class VTKIOVPIC_EXPORT vtkVPICReader : public vtkImageAlgorithm
{
public:
  static vtkVPICReader* New();
  vtkTypeMacro(vtkVPICReader, vtkImageAlgorithm);
  void PrintSelf(ostream& os, vtkIndent indent) override;

  ///@{
  /**
   * Specify file name of VPIC data file to read.
   */
  vtkSetStringMacro(FileName);
  vtkGetStringMacro(FileName);
  ///@}

  ///@{
  /**
   * Set the stride in each dimension
   */
  vtkSetVector3Macro(Stride, int);
  vtkGetVector3Macro(Stride, int);
  ///@}

  ///@{
  /**
   * Set the simulation file decomposition in each dimension
   */
  vtkSetVector2Macro(XExtent, int);
  vtkSetVector2Macro(YExtent, int);
  vtkSetVector2Macro(ZExtent, int);
  ///@}

  // Get the full layout size in files for setting the range in GUI
  vtkGetVector2Macro(XLayout, int);
  vtkGetVector2Macro(YLayout, int);
  vtkGetVector2Macro(ZLayout, int);

  ///@{
  /**
   * Get the reader's output
   */
  vtkImageData* GetOutput();
  vtkImageData* GetOutput(int index);
  ///@}

  ///@{
  /**
   * The following methods allow selective reading of solutions fields.
   * By default, ALL data fields on the nodes are read, but this can
   * be modified.
   */
  int GetNumberOfPointArrays();
  const char* GetPointArrayName(int index);
  int GetPointArrayStatus(const char* name);
  void SetPointArrayStatus(const char* name, int status);
  void DisableAllPointArrays();
  void EnableAllPointArrays();
  ///@}

protected:
  vtkVPICReader();
  ~vtkVPICReader() override;

  char* FileName; // First field part file giving path

  int Rank;      // Number of this processor
  int TotalRank; // Number of processors
  int UsedRank;  // Number of processors used in display

  VPICDataSet* vpicData;   // Data structure controlling access
  GridExchange* exchanger; // Exchange ghost cells between procs

  vtkIdType NumberOfNodes;  // Number of points in grid
  vtkIdType NumberOfCells;  // Number of cells in grid
  vtkIdType NumberOfTuples; // Number of tuples in sub extent

  int WholeExtent[6];  // Problem image extent
  int SubExtent[6];    // Processor problem extent
  int Dimension[3];    // Size of image
  int SubDimension[3]; // Size of subextent of image
  int XLayout[2];      // Extent in complete files
  int YLayout[2];      // Extent in complete files
  int ZLayout[2];      // Extent in complete files

  int NumberOfVariables;      // Number of variables to display
  vtkStdString* VariableName; // Names of each variable
  int* VariableStruct;        // Scalar, vector or tensor

  int NumberOfTimeSteps; // Temporal domain
  double* TimeSteps;     // Times available for request
  int CurrentTimeStep;   // Time currently displayed

  int Stride[3];  // Stride over actual data
  int XExtent[2]; // Subview extent in files
  int YExtent[2]; // Subview extent in files
  int ZExtent[2]; // Subview extent in files

  vtkFloatArray** data; // Actual data arrays
  int* dataLoaded;      // Data is loaded for current time

  int Start[3];            // Start offset for processor w ghosts
  int GhostDimension[3];   // Dimension including ghosts on proc
  int NumberOfGhostTuples; // Total ghost cells per component
  int ghostLevel0;         // Left plane number of ghosts
  int ghostLevel1;         // Right plane number of ghosts

  // Controls initializing and querrying MPI
  vtkMultiProcessController* MPIController;

  // Selected field of interest
  vtkDataArraySelection* PointDataArraySelection;

  // Observer to modify this object when array selections are modified
  vtkCallbackCommand* SelectionObserver;

  int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
  int RequestInformation(
    vtkInformation*, vtkInformationVector** inVector, vtkInformationVector*) override;

  void LoadVariableData(int var, int timeStep);
  void LoadComponent(float* varData, float* block, int comp, int numberOfComponents);

  static void SelectionCallback(
    vtkObject* caller, unsigned long eid, void* clientdata, void* calldata);
  static void EventCallback(vtkObject* caller, unsigned long eid, void* clientdata, void* calldata);

private:
  vtkVPICReader(const vtkVPICReader&) = delete;
  void operator=(const vtkVPICReader&) = delete;
};

#endif
