/*=========================================================================
*
*  Copyright NumFOCUS
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*         https://www.apache.org/licenses/LICENSE-2.0.txt
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*=========================================================================*/

// This code fragment is included in the test driver generated by the
// CMake command create_test_sourcelist. This is included directly after
// the call to the test main function. It performs optional redirection
// of test output and regression testing if needed.

if (redirectOutputParameters.redirect)
  {
  // Restore cout
  std::cout.rdbuf(oldCoutBuf);
  redirectStream.close();
  }

std::vector< HashPairType >& hashTestList = GetHashTestList();

// before the image to image compare we first check md5 hashes
for(auto & li : hashTestList)
  {
  const char * const testFilename = li.first;

  const int ret = HashTestImage( testFilename, li.second );
  if ( ret )
    {
    result = EXIT_FAILURE; //Nonzero indicates failure
    }
  }

RegressionTestParameters& regressionTestParameters = GetRegressionTestParameters();

// Make a list of possible baselines
for ( int ii = 0;
      ii < static_cast< int >( regressionTestParameters.compareList.size() );
      ii++ )
  {
  char * baselineFilename = regressionTestParameters.compareList[ii].first;
  char * testFilename =     regressionTestParameters.compareList[ii].second;
  std::map< std::string, int > baselines =
    RegressionTestBaselines(baselineFilename);
  auto baseline = baselines.begin();
  std::string bestBaseline = baseline->first;
  int  bestBaselineStatus = itk::NumericTraits< int >::max();
  bool oneReferenceImageWasReadable=false;
  while ( baseline != baselines.end() )
    {
    baseline->second =
      RegressionTestImage(testFilename,
                          ( baseline->first ).c_str(),
                          0,
                          regressionTestParameters.intensityTolerance,
                          regressionTestParameters.numberOfPixelsTolerance,
                          regressionTestParameters.radiusTolerance,
                          regressionTestParameters.verifyInputInformation,
                          regressionTestParameters.coordinateTolerance,
                          regressionTestParameters.directionTolerance);

    if ( baseline->second == itk::NumericTraits< int >::max() )
      {
      //Reference Image not found
      }
    else if ( baseline->second == itk::NumericTraits< int >::max() -2 )
      {
      //Test Image not found.  Immediate failure! (No further testing needed)
      break;
      }
    else if ( baseline->second == itk::NumericTraits< int >::max() -1 )
      {
      //Image dimensions do not match
      }
    else if ( baseline->second < bestBaselineStatus )
      {
      // A better image was found
      bestBaseline = baseline->first;
      bestBaselineStatus = baseline->second;
      oneReferenceImageWasReadable = true;
      }
    if ( baseline->second == 0 )
      {
      break;
      }
    ++baseline;
    }
  if ( oneReferenceImageWasReadable )
    {
    // if the best we can do still has errors, generate the error images
    if ( bestBaselineStatus  )
      {
      RegressionTestImage( testFilename,
        bestBaseline.c_str(),
        1,
        regressionTestParameters.intensityTolerance,
        regressionTestParameters.numberOfPixelsTolerance,
        regressionTestParameters.radiusTolerance,
        regressionTestParameters.verifyInputInformation,
        regressionTestParameters.coordinateTolerance,
        regressionTestParameters.directionTolerance);
        result = EXIT_FAILURE; //Nonzero indicates failure
      }
    // output the matching baseline
    std::cout << "<DartMeasurement name=\"BaselineImageName\" type=\"text/string\">"
              << itksys::SystemTools::GetFilenameName(bestBaseline)
              << "</DartMeasurement>" << std::endl;
    }
  else
    {
    std::cout << "<DartMeasurement name=\"BaselineImageName\" type=\"text/string\">"
              << "INVALID_BASELINE_GIVEN"
              << "</DartMeasurement>" << std::endl;
    result = EXIT_FAILURE; //Nonzero indicates failure
    }
  }
}
  catch ( const itk::ExceptionObject & e )
    {
    std::cerr << "ITK test driver caught an ITK exception:\n";
    e.Print(std::cerr);
    result = EXIT_FAILURE;
    }
  catch ( const std::exception & e )
    {
    std::cerr << "ITK test driver caught an exception:\n";
    std::cerr << e.what() << "\n";
    result = EXIT_FAILURE;
    }
  catch ( ... )
    {
    std::cerr << "ITK test driver caught an unknown exception!!!\n";
    result = EXIT_FAILURE;
    }
