// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
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)

}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int QFilterParametersWriter::WritePipelineToFile(FilterPipeline::Pointer pipeline, const QString& filePath, const QString& name, QSettings::Format format, IObserver* obs)
{

  if(NULL == pipeline.get())
  {
    if(NULL != obs)
    {
      PipelineMessage pm(QFilterParametersWriter::ClassName(), "FilterPipeline Object was NULL for writing", -1, PipelineMessage::Error);
      obs->processPipelineMessage(pm);
    }
    return -1;
  }

  FilterPipeline::FilterContainerType& filters = pipeline->getFilterContainer();

  QFilterParametersWriter::Pointer writer = QFilterParametersWriter::New();
  // This will open the file, and write/update the initial group of settings like the name and DREAM3D Version
  writer->openFile(filePath, format);
  // Loop over each filter and write it's input parameters to the file
  int count = filters.size();
  int index = 0;
  for(qint32 i = 0; i < count; ++i)
  {
    AbstractFilter::Pointer filter = filters.at(i);
    if(NULL != filter.get())
    {
      index = filter->writeFilterParameters(writer.get(), index);
    }
    else
    {
      AbstractFilter::Pointer badFilter = AbstractFilter::New();
      writer->openFilterGroup(badFilter.get(), i);
      writer->writeValue("Unkown Filter", "ERROR: Filter instance was NULL within the PipelineFilterWidget instance. Report this error to the DREAM3D Developers");
      writer->closeFilterGroup();
    }
  }

  writer->setNumberOfFilters(index);
  writer->setPipelineName(name);
  writer->closeFile(); // Close the file
  return 0;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int H5FilterParametersWriter::WritePipelineToFile(FilterPipeline::Pointer pipeline, QString filePath, QString name, IObserver* obs)
{
  if (NULL == pipeline.get())
  {
    if (NULL != obs)
    {
      PipelineMessage pm(H5FilterParametersWriter::ClassName(), "FilterPipeline Object was NULL for writing", -1, PipelineMessage::Error);
      obs->processPipelineMessage(pm);
    }
    return -1;
  }

  QFileInfo fileInfo(filePath);

  // WRITE THE PIPELINE TO THE HDF5 FILE
  H5FilterParametersWriter::Pointer writer = H5FilterParametersWriter::New();

  hid_t fileId = -1;

  fileId = QH5Utilities::createFile(filePath);
  if (fileId < 0)
  {
    if (NULL != obs)
    {
      PipelineMessage pm(H5FilterParametersWriter::ClassName(), "Output .dream3d file could not be created.", -1, PipelineMessage::Error);
      obs->processPipelineMessage(pm);
    }
    return -1;
  }

  // This will make sure if we return early from this method that the HDF5 File is properly closed.
  // This will also take care of making sure all groups and file ids are closed
  // before this method returns.
  HDF5ScopedFileSentinel scopedFileSentinel(&fileId, true);

  // Write our File Version string to the Root "/" group
  QH5Lite::writeStringAttribute(fileId, "/", DREAM3D::HDF5::FileVersionName, DREAM3D::HDF5::FileVersion);
  QH5Lite::writeStringAttribute(fileId, "/", DREAM3D::HDF5::DREAM3DVersion, DREAM3DLib::Version::Complete() );

  hid_t pipelineGroupId = QH5Utilities::createGroup(fileId, DREAM3D::StringConstants::PipelineGroupName);
  scopedFileSentinel.addGroupId(&pipelineGroupId);
  writer->setGroupId(pipelineGroupId);

  FilterPipeline::FilterContainerType& filters = pipeline->getFilterContainer();

  // Loop over each filter and write it's input parameters to the file
  int count = filters.size();
  int index = 0;
  for (qint32 i = 0; i < count; ++i)
  {
    AbstractFilter::Pointer filter = filters.at(i);
    if (NULL != filter.get())
    {
      index = filter->writeFilterParameters(writer.get(), index);
    }
    else
    {
      AbstractFilter::Pointer badFilter = AbstractFilter::New();
      writer->openFilterGroup(badFilter.get(), i);
      writer->writeValue("Unknown Filter", "ERROR: Filter instance was NULL within the PipelineFilterWidget instance. Report this error to the DREAM3D Developers");
      writer->closeFilterGroup();
    }
  }

  return 0;
}