/*=========================================================================

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/VolViewCopyright.htm 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 "vtkVVTesting.h"

#include "vtkObjectFactory.h"
#include "vtkKWRenderWidget.h"
#include "vtkImageAppend.h"
#include "vtkImageResample.h"
#include "vtkImageData.h"
#include "vtkSmartPointer.h"
#include "vtkJPEGWriter.h"
#include "vtkImageShiftScale.h"
#include "vtkPNGReader.h"
#include "vtkTesting.h"
#include "vtkWindowToImageFilter.h"
#include "vtkRenderWindow.h"

//----------------------------------------------------------------------------
vtkStandardNewMacro( vtkVVTesting );
vtkCxxRevisionMacro(vtkVVTesting, "$Revision: 1.7 $");

vtkCxxSetObjectMacro(vtkVVTesting,RenderView,vtkKWRenderWidget);
vtkCxxSetObjectMacro(vtkVVTesting,ImageData ,vtkImageData);

//----------------------------------------------------------------------------
vtkVVTesting::vtkVVTesting()
{
  this->Testing = vtkTesting::New();
  this->Testing->SetBorderOffset(17);
  this->RenderView = 0;
  this->ImageData  = 0;
  this->ComparisonImage = 0;
  this->AppendFilter = 0;
  this->PrintBaselinesToDashboard = 1;
}

//----------------------------------------------------------------------------
vtkVVTesting::~vtkVVTesting()
{
  this->SetRenderView(0);
  this->Testing->Delete();
  this->Testing = 0;
  this->SetComparisonImage(0);
  if (this->AppendFilter)
    {
    this->AppendFilter->Delete();
    this->AppendFilter = 0;
    }
  if (this->ImageData)
    {
    this->ImageData->UnRegister(this);
    this->ImageData = NULL;
    }
}

//----------------------------------------------------------------------------
void vtkVVTesting::AddArgument(const char* arg)
{
  this->Testing->AddArgument(arg);
}

//----------------------------------------------------------------------------
int vtkVVTesting::RegressionTest(float thresh)
{
  int res = vtkTesting::FAILED;
  if ( this->ImageData )
    {
    res = this->Testing->RegressionTest(this->ImageData, thresh);
    }
  if ( this->RenderView )
    {
    this->Testing->SetRenderWindow(this->RenderView->GetRenderWindow());
    res = this->Testing->RegressionTest(thresh);
    }
  if ( this->ComparisonImage )
    {
    vtkPNGReader* reader = vtkPNGReader::New();
    reader->SetFileName(this->ComparisonImage);
    reader->Update();
    res = this->Testing->RegressionTest(reader->GetOutput(), thresh);
    reader->Delete();
    }
  if ( this->AppendFilter )
    {
    this->AppendFilter->Update();
    res = 
      this->Testing->RegressionTest(this->AppendFilter->GetOutput(), thresh);
    }

  if (res == vtkTesting::PASSED && PrintBaselinesToDashboard)
    {
    this->DisplayBaselineImageOnDashboard();
    }
     
    
  return res != vtkTesting::PASSED;
}

//----------------------------------------------------------------------------
void vtkVVTesting::DisplayBaselineImageOnDashboard()
{
  const char * tmpDir = this->Testing->GetTempDirectory();
  vtkSmartPointer<vtkPNGReader> rt_png = vtkSmartPointer<vtkPNGReader>::New();
  rt_png->SetFileName(this->Testing->GetValidImageFileName()); 
  rt_png->Update();
  
  int* rt_size = rt_png->GetOutput()->GetDimensions();
  double rt_magfactor=1.0;
  if ( rt_size[1] > 250.0)
    {
    rt_magfactor = 250.0 / rt_size[1];
    }

  vtkImageResample*  rt_shrink = vtkImageResample::New();
  rt_shrink->SetInput(rt_png->GetOutput());
  rt_shrink->InterpolateOn();
  rt_shrink->SetAxisMagnificationFactor(0, rt_magfactor );
  rt_shrink->SetAxisMagnificationFactor(1, rt_magfactor );

  vtkstd::string validName = this->Testing->GetValidImageFileName();
  vtkstd::string::size_type slash_pos = validName.rfind("/");
  if(slash_pos != vtkstd::string::npos)
    {
    validName = validName.substr(slash_pos + 1);
    }  

  vtkJPEGWriter* rt_jpegw_dashboard = vtkJPEGWriter::New();
  rt_jpegw_dashboard->SetInput (rt_shrink->GetOutput());
  char* valid = new char[strlen(tmpDir) + validName.size() + 30];
  sprintf(valid, "%s/%s.small.jpg", tmpDir, validName.c_str());
  rt_jpegw_dashboard-> SetFileName(valid);
  rt_jpegw_dashboard->Write();
  rt_jpegw_dashboard->Delete();
  rt_shrink->Delete();

  cout << "<DartMeasurementFile name=\"Baseline\" type=\"image/jpeg\">";
  cout << valid;
  cout <<  "</DartMeasurementFile>";

  delete [] valid;
}

//----------------------------------------------------------------------------
void vtkVVTesting::DisplayImageOnDashboard( vtkImageData *image, 
                                  const char * suffix, const char *comment)
{
  const char * tmpDir = this->Testing->GetTempDirectory();
  
  int* rt_size = image->GetDimensions();
  double rt_magfactor=1.0;
  if ( rt_size[1] > 250.0)
    {
    rt_magfactor = 250.0 / rt_size[1];
    }

  vtkImageResample*  rt_shrink = vtkImageResample::New();
  rt_shrink->SetInput(image);
  rt_shrink->InterpolateOn();
  rt_shrink->SetAxisMagnificationFactor(0, rt_magfactor );
  rt_shrink->SetAxisMagnificationFactor(1, rt_magfactor );

  vtkstd::string validName = this->Testing->GetValidImageFileName();
  vtkstd::string::size_type slash_pos = validName.rfind("/");
  if(slash_pos != vtkstd::string::npos)
    {
    validName = validName.substr(slash_pos + 1);
    }  

  vtkJPEGWriter* rt_jpegw_dashboard = vtkJPEGWriter::New();
  rt_jpegw_dashboard->SetInput (rt_shrink->GetOutput());

  std::string suffixString( suffix );
  slash_pos = suffixString.rfind("/");
  if(slash_pos != vtkstd::string::npos)
    {
    suffixString = suffixString.substr(slash_pos + 1);
    }  

  char* valid = new char[strlen(tmpDir) + validName.size() + suffixString.size() + 30];
  sprintf(valid, "%s/%s-%s.small.jpg", tmpDir, validName.c_str(), suffixString.c_str());
  
  rt_jpegw_dashboard-> SetFileName(valid);
  rt_jpegw_dashboard->Write();
  rt_jpegw_dashboard->Delete();
  rt_shrink->Delete();

  cout << "<DartMeasurementFile name=\"" << comment << 
    "\" type=\"image/jpeg\">" << valid;
  cout <<  "</DartMeasurementFile>" << endl;

  delete [] valid;
}


//----------------------------------------------------------------------------
void vtkVVTesting::AppendTestImage(vtkKWRenderWidget *renderView)
{
  if (!renderView)
    {
    return;
    }
  
  if (!this->AppendFilter)
    {
    this->AppendFilter = vtkImageAppend::New();
    }

  vtkWindowToImageFilter *w2i = vtkWindowToImageFilter::New();
  w2i->SetInput(renderView->GetRenderWindow());
  w2i->Update();
  
  this->AppendFilter->AddInput(w2i->GetOutput());
  w2i->GetOutput()->SetSource(0);
  w2i->Delete();
}

//----------------------------------------------------------------------------
void vtkVVTesting::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  os << indent << "RenderView: " << this->RenderView << endl;
  os << indent << "ComparisonImage: " 
    << (this->ComparisonImage?this->ComparisonImage:"(none)") << endl;
}


