// For comment from VTK Developers (developer a.maclean@cas.edu.au).
// Testing particle reader.
// Read in a file of particles and output a 
// .vtp file.

#include <iostream>
#include <stdexcept>
#include <string>
#include <fstream>
#include <iomanip>
#include <sstream>

#include <vtkCommand.h>
#include <vtkSmartPointer.h>

#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>

#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkXMLPolyDataWriter.h>


#include "ParticleReader.h" 

class vtkStartCommand : public vtkCommand
{
public:
  static vtkStartCommand *New() { return new vtkStartCommand; }
  virtual void Execute(vtkObject * caller, unsigned long, void * /*callData*/)
  { vtkstd::cout << "Starting execution of " << caller->GetClassName() << std::endl; }
};

class vtkEndCommand : public vtkCommand
{
public:
  static vtkEndCommand *New() { return new vtkEndCommand; }
  virtual void Execute(vtkObject * caller, unsigned long, void * /*callData*/)
  { 
    vtkstd::ostringstream os;
    os << "Execution ended for " << caller->GetClassName();
    cout << os.str() << vtkstd::endl;
  }
};

class vtkProgressCommand : public vtkCommand
{
public:
  static vtkProgressCommand *New() { return new vtkProgressCommand; }
  virtual void Execute(vtkObject *caller, unsigned long, void *callData)
  { double progress = *(static_cast<double*>(callData))*100.0; 
         vtkstd::cout << "Progress at " << (int)progress << "% for " << caller->GetClassName() << "." << vtkstd::endl; } 
};



int main ( int argc, char* argv[] )
{
  if ( argc != 3 ) 
    {
    vtkstd::cout << "Need input file and output file." << vtkstd::endl;
    return 1;
    }

  vtkstd::string ifn = argv[1];
  vtkstd::string ofn = argv[2];

  vtkstd::cerr << "Input file: " << ifn << vtkstd::endl;
  vtkstd::cerr << "Output file: " << ofn << vtkstd::endl; 

  if ( ifn == ofn )
    {
    vtkstd::cerr << "File names cannot be the same." << vtkstd::endl;
    return 1;
    }

  vtkSmartPointer<vtkStartCommand> sobserver = vtkSmartPointer<vtkStartCommand>::New();
  vtkSmartPointer<vtkEndCommand> eobserver = vtkSmartPointer<vtkEndCommand>::New();
  vtkSmartPointer<vtkProgressCommand> pobserver = vtkSmartPointer<vtkProgressCommand>::New();

  vtkSmartPointer<ParticleReader> pr = vtkSmartPointer<ParticleReader>::New();
    pr->SetFileName(ifn.c_str());
    pr->AddObserver( vtkCommand::StartEvent, sobserver );
    pr->AddObserver( vtkCommand::EndEvent, eobserver );
    pr->AddObserver( vtkCommand::ProgressEvent, pobserver );

  vtkSmartPointer<vtkPolyData> pd = vtkSmartPointer<vtkPolyData>::New();
    pr->HasValueOn();
    pr->Update();
    
//    pr->Print(vtkstd::cout);
  
  vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
  vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
  vtkSmartPointer<vtkRenderWindowInteractor> iRen = vtkSmartPointer<vtkRenderWindowInteractor>::New();

    renWin->AddRenderer(ren);
    iRen->SetRenderWindow(renWin);
  
  vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
  
  vtkSmartPointer<vtkXMLPolyDataWriter> writer = vtkSmartPointer<vtkXMLPolyDataWriter>::New();
  
  writer->SetInput(pr->GetOutput());
  writer->SetFileName(ofn.c_str());
  writer->Write();
  
    mapper->SetInput(pr->GetOutput());
    actor->SetMapper(mapper);
    ren->AddViewProp(actor);
  
    ren->Render();
    iRen->Initialize();
    iRen->Start();
  
  return 0;
}
