//============================================================================
//  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 <vector>

#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayRangeCompute.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/ScatterPermutation.h>
#include <vtkm/worklet/WorkletMapTopology.h>

int main(int argc, char** argv)
{
#ifdef FIDES_USE_MPI
  MPI_Init(&argc, &argv);
#endif

  int retVal = 0;
  fides::io::DataSetReader reader(argv[1]);
  std::unordered_map<std::string, std::string> paths;
  paths["source"] = std::string(argv[2]) + "/structured.bp";

  auto metaData = reader.ReadMetaData(paths);

  vtkm::cont::PartitionedDataSet output = reader.ReadDataSet(paths, fides::metadata::MetaData());
  if (output.GetNumberOfPartitions() != 2)
  {
    std::cerr << "Error: expected 2 output blocks, 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] != 6 || dims[1] != 6 || dims[2] != 9)
  {
    std::cerr << "Dimensions do not match for partitions 0. Expected 9 6 6" << std::endl;
    retVal = 1;
  }

  const auto& denField = ds.GetField("density");
  const auto& denHandle = denField.GetData().AsArrayHandle<vtkm::cont::ArrayHandle<float>>();
  vtkm::cont::ArrayHandle<vtkm::Range> rangeArray = vtkm::cont::ArrayRangeCompute(denHandle);
  auto rangePortal = rangeArray.ReadPortal();
  if (rangePortal.Get(0).Min > 0.20301 || rangePortal.Get(0).Min < 0.2029)
  {
    std::cerr << "Unexpected density min range. Got " << rangePortal.Get(0).Min << std::endl;
    retVal = 1;
  }
  if (rangePortal.Get(0).Max > 0.71042 || rangePortal.Get(0).Max < 0.7104)
  {
    std::cerr << "Unexpected density max range. Got " << rangePortal.Get(0).Max << std::endl;
    retVal = 1;
  }

#ifdef FIDES_USE_MPI
  MPI_Finalize();
#endif
  return retVal;
}
