// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void ExecutePipeline(const QString& pipelineFile)
{
  int err = EXIT_SUCCESS;

  // Sanity Check the filepath to make sure it exists, Report an error and bail if it does not
  QFileInfo fi(pipelineFile);
  std::cout << "<--------------Test Pipeline File: " << fi.absoluteFilePath().toStdString() << " --------------------------->" << std::endl;
  if(fi.exists() == false)
  {
    std::cout << "The input file '" << pipelineFile.toStdString() << "' does not exist" << std::endl;
    err = EXIT_FAILURE;
  }
  DREAM3D_REQUIRE_EQUAL(err, EXIT_SUCCESS)

  QString ext = fi.completeSuffix();

  // Use the static method to read the Pipeline file and return a Filter Pipeline
  FilterPipeline::Pointer pipeline;
  if (ext == "ini" || ext == "txt")
  {
    pipeline = QFilterParametersReader::ReadPipelineFromFile(pipelineFile, QSettings::IniFormat);
  }
  else if (ext == "dream3d")
  {
    pipeline = H5FilterParametersReader::ReadPipelineFromFile(pipelineFile);
  }
  else if (ext == "json")
  {
    pipeline = JsonFilterParametersReader::ReadPipelineFromFile(pipelineFile);
  }

  if (NULL == pipeline.get())
  {
    std::cout << "An error occurred trying to read the pipeline file. Exiting now." << std::endl;
    err = EXIT_FAILURE;
  }
  DREAM3D_REQUIRE_EQUAL(err, EXIT_SUCCESS)


  Observer obs; // Create an Observer to report errors/progress from the executing pipeline
  pipeline->addMessageReceiver(&obs);
  // Preflight the pipeline
  err = pipeline->preflightPipeline();
  if (err < 0)
  {
    std::cout << "Errors preflighting the pipeline. Exiting Now." << std::endl;
  }
  DREAM3D_REQUIRE_EQUAL(err, EXIT_SUCCESS)

  // Now actually execute the pipeline
  pipeline->execute();
  err = pipeline->getErrorCondition();
  if (err < 0)
  {
    std::cout << "Error Condition of Pipeline: " << err << std::endl;
    err = EXIT_FAILURE;
  }
  DREAM3D_REQUIRE_EQUAL(err, EXIT_SUCCESS)

}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void FilterParametersRWTest()
{
  // Create our Pipeline object
  FilterPipeline::Pointer pipeline = FilterPipeline::New();


  GenericFilter::Pointer filt = GenericFilter::New();

  // Set something for each and every property so you have something to compare against.
  // You may want to make some constants for these values
  filt->setStlFilePrefix(StlFilePrefixTestValue);
  filt->setMaxIterations(MaxIterationsTestValue);
  filt->setMisorientationTolerance(MisorientationToleranceTestValue);
  filt->setInputFile(InputFileTestValue);
  filt->setInputPath(InputPathTestValue);
  filt->setOutputFile(OutputFileTestValue);
  filt->setOutputPath(OutputPathTestValue);
  filt->setWriteAlignmentShifts(WriteAlignmentShiftsTestValue);
  filt->setConversionType(ConversionTypeTestValue);
  filt->setSelectedCellArrayName(SelectedCellArrayNameTestValue);
  filt->setSelectedFieldArrayName(SelectedFieldArrayNameTestValue);
  filt->setSelectedEnsembleArrayName(SelectedEnsembleArrayNameTestValue);
  filt->setSurfaceMeshPointArrayName(SurfaceMeshPointArrayNameTestValue);
  filt->setSurfaceMeshFaceArrayName(SurfaceMeshFaceArrayNameTestValue);
  filt->setSurfaceMeshEdgeArrayName(SurfaceMeshEdgeArrayNameTestValue);
  filt->setSolidMeshPointArrayName(SolidMeshPointArrayNameTestValue);
  filt->setSolidMeshFaceArrayName(SolidMeshFaceArrayNameTestValue);
  filt->setSolidMeshEdgeArrayName(SolidMeshEdgeArrayNameTestValue);

  ComparisonInput_t comparison1;
  comparison1.arrayName = Comparison1InputArrayNameTestValue;
  comparison1.compOperator = Comparison1CompOperatorTestValue;
  comparison1.compValue = Comparison1CompValueTestValue;

  ComparisonInput_t comparison2;
  comparison2.arrayName = Comparison2InputArrayNameTestValue;
  comparison2.compOperator = Comparison2CompOperatorTestValue;
  comparison2.compValue = Comparison2CompValueTestValue;

  std::vector<ComparisonInput_t> comparisonVector;
  comparisonVector.push_back(comparison1);
  comparisonVector.push_back(comparison2);
  filt->setCellComparisonInputs(comparisonVector);

  AxisAngleInput_t axisAngles1;
  axisAngles1.angle = AxisAngles1AngleTestValue;
  axisAngles1.h = AxisAngles1HTestValue;
  axisAngles1.k = AxisAngles1KTestValue;
  axisAngles1.l = AxisAngles1LTestValue;

  AxisAngleInput_t axisAngles2;
  axisAngles2.angle = AxisAngles2AngleTestValue;
  axisAngles2.h = AxisAngles2HTestValue;
  axisAngles2.k = AxisAngles2KTestValue;
  axisAngles2.l = AxisAngles2LTestValue;

  std::vector<AxisAngleInput_t> axisAngleInputsVector;
  axisAngleInputsVector.push_back(axisAngles1);
  axisAngleInputsVector.push_back(axisAngles2);
  filt->setAxisAngleRotations(axisAngleInputsVector);

  DataContainerWriter::Pointer writer = DataContainerWriter::New();
  writer->setOutputFile(UnitTest::FilterParametersRWTest::OutputFile);

  pipeline->pushBack(filt);
  pipeline->pushBack(writer);

  pipeline->execute();
  int err = pipeline->getErrorCondition();
  DREAM3D_REQUIRED(err, >= , 0)


  // We are done writing a file, now we need to read the file using raw HDF5 codes

  hid_t fid = H5Utilities::openFile(UnitTest::FilterParametersRWTest::OutputFile);
  DREAM3D_REQUIRED(fid, >, 0)

  H5FilterParametersReader::Pointer reader = H5FilterParametersReader::New();

  hid_t pipelineGroupId = H5Gopen(fid, DREAM3D::HDF5::PipelineGroupName.c_str(), H5P_DEFAULT);
  reader->setGroupId(pipelineGroupId);

  err = reader->openFilterGroup( filt.get(), 0); // Open the HDF5 Group for this filter
  DREAM3D_REQUIRED(err, >=, 0)

  // This next line should read all the filter parameters into the filter.
  filt->readFilterParameters( reader.get(), 0);

  // Now one by one, compare each of the filter parameters that you have stored in some constant somewhere to the values that are now in the filt variable.
  // Use DREAM3D_REQUIRED() to make sure each one is what you think it is.
  DREAM3D_REQUIRED(StlFilePrefixTestValue, ==, filt->getStlFilePrefix() )
  DREAM3D_REQUIRED(MaxIterationsTestValue, ==, filt->getMaxIterations() )
  DREAM3D_REQUIRED(MisorientationToleranceTestValue, ==, filt->getMisorientationTolerance() )
  DREAM3D_REQUIRED(InputFileTestValue, ==, filt->getInputFile() )
  DREAM3D_REQUIRED(InputPathTestValue, ==, filt->getInputPath() )
  DREAM3D_REQUIRED(OutputFileTestValue, ==, filt->getOutputFile() )
  DREAM3D_REQUIRED(OutputPathTestValue, ==, filt->getOutputPath() )
  DREAM3D_REQUIRED(WriteAlignmentShiftsTestValue, ==, filt->getWriteAlignmentShifts() )
  DREAM3D_REQUIRED(ConversionTypeTestValue, ==, filt->getConversionType() )
  DREAM3D_REQUIRED(SelectedCellArrayNameTestValue, ==, filt->getSelectedCellArrayName() )
  DREAM3D_REQUIRED(SelectedFieldArrayNameTestValue, ==, filt->getSelectedFieldArrayName() )
  DREAM3D_REQUIRED(SelectedEnsembleArrayNameTestValue, ==, filt->getSelectedEnsembleArrayName() )
  DREAM3D_REQUIRED(SurfaceMeshPointArrayNameTestValue, ==, filt->getSurfaceMeshPointArrayName() )
  DREAM3D_REQUIRED(SurfaceMeshFaceArrayNameTestValue, ==, filt->getSurfaceMeshFaceArrayName() )
  DREAM3D_REQUIRED(SurfaceMeshEdgeArrayNameTestValue, ==, filt->getSurfaceMeshEdgeArrayName() )
  DREAM3D_REQUIRED(SolidMeshPointArrayNameTestValue, ==, filt->getSolidMeshPointArrayName() )
  DREAM3D_REQUIRED(SolidMeshFaceArrayNameTestValue, ==, filt->getSolidMeshFaceArrayName() )
  DREAM3D_REQUIRED(SolidMeshEdgeArrayNameTestValue, ==, filt->getSolidMeshEdgeArrayName() )

  // Test the CellComparisonInputs widget
  std::vector<ComparisonInput_t> comparisonVectorRead = filt->getCellComparisonInputs();
  ComparisonInput_t comparison1Read = comparisonVectorRead[0];
  ComparisonInput_t comparison2Read = comparisonVectorRead[1];

  DREAM3D_REQUIRED(comparison1.arrayName, ==, comparison1Read.arrayName)
  DREAM3D_REQUIRED(comparison1.compOperator, ==, comparison1Read.compOperator)
  DREAM3D_REQUIRED(comparison1.compValue, ==, comparison1Read.compValue)
  DREAM3D_REQUIRED(comparison2.arrayName, ==, comparison2Read.arrayName)
  DREAM3D_REQUIRED(comparison2.compOperator, ==, comparison2Read.compOperator)
  DREAM3D_REQUIRED(comparison2.compValue, ==, comparison2Read.compValue)

  // Test the AxisAngleInput widget
  std::vector<AxisAngleInput_t> axisAngleVectorRead = filt->getAxisAngleRotations();
  AxisAngleInput_t axisAngles1Read = axisAngleVectorRead[0];
  AxisAngleInput_t axisAngles2Read = axisAngleVectorRead[1];

  DREAM3D_REQUIRED(axisAngles1.angle, ==, axisAngles1Read.angle)
  DREAM3D_REQUIRED(axisAngles1.h, ==, axisAngles1Read.h)
  DREAM3D_REQUIRED(axisAngles1.k, ==, axisAngles1Read.k)
  DREAM3D_REQUIRED(axisAngles1.l, ==, axisAngles1Read.l)
  DREAM3D_REQUIRED(axisAngles2.angle, ==, axisAngles2Read.angle)
  DREAM3D_REQUIRED(axisAngles2.h, ==, axisAngles2Read.h)
  DREAM3D_REQUIRED(axisAngles2.k, ==, axisAngles2Read.k)
  DREAM3D_REQUIRED(axisAngles2.l, ==, axisAngles2Read.l)

  err = reader->closeFilterGroup(); // Close the HDF5 group for this filter
  DREAM3D_REQUIRED(err, >=, 0)


  H5Gclose(pipelineGroupId); // Closes the "Pipeline" group
  H5Fclose(fid); // Closes the file
}