//============================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt 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.
//
//============================================================================

#include <fides/DataSetReader.h>
#ifdef FIDES_USE_MPI
#include <mpi.h>
#endif
#include <string>
#include <unordered_map>

#include <vtkm/cont/ArrayHandleBasic.h>
#include <vtkm/cont/ArrayRangeCompute.h>
#include <vtkm/io/VTKDataSetWriter.h>

int main(int argc, char** argv)
{
  if (argc < 3)
  {
    std::cerr << "Usage ./test-gem <name of the json file> <path of data source folder>"
                 "<optional write data>\n";
    std::cerr << "Example: ./test-gem ~/fides/tests/test-gem.json ~/fides/tests/data 1\n"
                 "\tThis outputs the data in .vtk format.\n";
    return 0;
  }

#ifdef FIDES_USE_MPI
  MPI_Init(&argc, &argv);
#endif

  bool writeVTK = false;
  if (argc == 4)
  {
    writeVTK = std::atoi(argv[3]) == 1;
  }
  int retVal = 0;
  fides::io::DataSetReader reader(argv[1]);
  std::unordered_map<std::string, std::string> paths;
  paths["source"] = std::string(argv[2]) + "/";

  auto metaData = reader.ReadMetaData(paths);

  vtkm::cont::PartitionedDataSet output = reader.ReadDataSet(paths, metaData);
  if (output.GetNumberOfPartitions() != 1)
  {
    std::cerr << "Error: expected 1 output block, got " << output.GetNumberOfPartitions()
              << std::endl;
    retVal = 1;
  }
  vtkm::cont::DataSet ds = output.GetPartition(0);
  vtkm::cont::UnknownCellSet cellSet = ds.GetCellSet();
  vtkm::cont::CellSetStructured<3> css = cellSet.AsCellSet<vtkm::cont::CellSetStructured<3>>();
  auto dims = css.GetPointDimensions();
  std::cout << dims[0] << " " << dims[1] << " " << dims[2] << std::endl;
  if (dims[0] != 259 || dims[1] != 129 || dims[2] != 9)
  {
    std::cerr << "Dimensions do not match for partitions 0. Expected 259, 129, 9" << std::endl;
    retVal = 1;
  }

  const auto& den = ds.GetField("gem_density");
  const auto& denHandle = den.GetData().AsArrayHandle<vtkm::cont::ArrayHandle<double>>();
  auto rangeArray = vtkm::cont::ArrayRangeCompute(denHandle);
  auto rangePortal = rangeArray.ReadPortal();
  if (rangePortal.Get(0).Min > -45243071.45613 || rangePortal.Get(0).Min < -45243071.45614)
  {
    std::cerr << "Unexpected gem_density min range. Got " << rangePortal.Get(0).Min << std::endl;
    retVal = 1;
  }
  if (rangePortal.Get(0).Max > 44002582.34138 || rangePortal.Get(0).Max < 44002582.34137)
  {
    std::cerr << "Unexpected gem_density max range. Got " << rangePortal.Get(0).Max << std::endl;
    retVal = 1;
  }

  if (writeVTK)
  {
    auto& outputData = output.GetPartition(0);
    std::cout << "writing output in vtk format...\n";
    vtkm::io::VTKDataSetWriter writer("gem-output.vtk");
    writer.WriteDataSet(outputData);
  }
#ifdef FIDES_USE_MPI
  MPI_Finalize();
#endif
  return retVal;
}
