#include <vtkm/io/reader/VTKDataSetReader.h>

#include <vtkm/rendering/Actor.h>
#include <vtkm/rendering/Camera.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/MapperPoint.h>
#include <vtkm/rendering/MapperRayTracer.h>
#include <vtkm/rendering/MapperWireframer.h>
#include <vtkm/rendering/View3D.h>

#include <vtkm/cont/testing/Testing.h>

namespace
{

void DoBasicRender()
{
  // Load some data to render
  vtkm::cont::DataSet surfaceData;
  try
  {
    vtkm::io::reader::VTKDataSetReader reader("data/cow.vtk");
    surfaceData = reader.ReadDataSet();
  }
  catch (vtkm::io::ErrorIO& error)
  {
    std::cout << "Could not read file:" << std::endl
              << error.GetMessage() << std::endl;
    exit(1);
  }
  catch (...)
  {
    throw;
  }

  // Initialize VTK-m rendering classes
  ////
  //// BEGIN-EXAMPLE ConstructView.cxx
  ////
  ////
  //// BEGIN-EXAMPLE ActorScene.cxx
  ////
  vtkm::rendering::Actor actor(surfaceData.GetCellSet(),
                               surfaceData.GetCoordinateSystem(),
                               surfaceData.GetField("RandomPointScalars"));

  vtkm::rendering::Scene scene;
  scene.AddActor(actor);
  ////
  //// END-EXAMPLE ActorScene.cxx
  ////

  vtkm::rendering::MapperRayTracer mapper;
  ////
  //// BEGIN-EXAMPLE Canvas.cxx
  ////
  vtkm::rendering::CanvasRayTracer canvas(1920, 1080);
  ////
  //// END-EXAMPLE Canvas.cxx
  ////

  vtkm::rendering::View3D view(scene, mapper, canvas);
  view.Initialize();
  ////
  //// END-EXAMPLE ConstructView.cxx
  ////

  ////
  //// BEGIN-EXAMPLE ViewColors.cxx
  ////
  view.SetBackgroundColor(vtkm::rendering::Color(1.0f, 1.0f, 1.0f));
  view.SetForegroundColor(vtkm::rendering::Color(0.0f, 0.0f, 0.0f));
  ////
  //// END-EXAMPLE ViewColors.cxx
  ////

  ////
  //// BEGIN-EXAMPLE PaintView.cxx
  ////
  view.Paint();
  ////
  //// END-EXAMPLE PaintView.cxx
  ////

  ////
  //// BEGIN-EXAMPLE SaveView.cxx
  ////
  view.SaveAs("BasicRendering.ppm");
  ////
  //// END-EXAMPLE SaveView.cxx
  ////
}

void DoPointRender()
{
  // Load some data to render
  vtkm::cont::DataSet surfaceData;
  try
  {
    vtkm::io::reader::VTKDataSetReader reader("data/cow.vtk");
    surfaceData = reader.ReadDataSet();
  }
  catch (vtkm::io::ErrorIO& error)
  {
    std::cout << "Could not read file:" << std::endl
              << error.GetMessage() << std::endl;
    exit(1);
  }
  catch (...)
  {
    throw;
  }

  // Initialize VTK-m rendering classes
  vtkm::rendering::Actor actor(surfaceData.GetCellSet(),
                               surfaceData.GetCoordinateSystem(),
                               surfaceData.GetField("RandomPointScalars"));

  vtkm::rendering::Scene scene;
  scene.AddActor(actor);

  vtkm::rendering::CanvasRayTracer canvas(1920, 1080);

  ////
  //// BEGIN-EXAMPLE MapperPoint.cxx
  ////
  vtkm::rendering::MapperPoint mapper;
  mapper.UseVariableRadius(true);
  mapper.SetRadiusDelta(10.0f);

  vtkm::rendering::View3D view(scene, mapper, canvas);
  ////
  //// END-EXAMPLE MapperPoint.cxx
  ////

  view.Initialize();

  view.SetBackgroundColor(vtkm::rendering::Color(1.0f, 1.0f, 1.0f));
  view.SetForegroundColor(vtkm::rendering::Color(0.0f, 0.0f, 0.0f));

  view.Paint();

  view.SaveAs("PointRendering.ppm");
}

void DoEdgeRender()
{
  // Load some data to render
  vtkm::cont::DataSet surfaceData;
  try
  {
    vtkm::io::reader::VTKDataSetReader reader("data/cow.vtk");
    surfaceData = reader.ReadDataSet();
  }
  catch (vtkm::io::ErrorIO& error)
  {
    std::cout << "Could not read file:" << std::endl
              << error.GetMessage() << std::endl;
    exit(1);
  }
  catch (...)
  {
    throw;
  }

  // Initialize VTK-m rendering classes
  vtkm::rendering::Actor actor(surfaceData.GetCellSet(),
                               surfaceData.GetCoordinateSystem(),
                               surfaceData.GetField("RandomPointScalars"));

  vtkm::rendering::Scene scene;
  scene.AddActor(actor);

  vtkm::rendering::CanvasRayTracer canvas(1920, 1080);

  ////
  //// BEGIN-EXAMPLE MapperEdge.cxx
  ////
  vtkm::rendering::MapperWireframer mapper;
  vtkm::rendering::View3D view(scene, mapper, canvas);
  ////
  //// END-EXAMPLE MapperEdge.cxx
  ////

  view.Initialize();

  view.SetBackgroundColor(vtkm::rendering::Color(1.0f, 1.0f, 1.0f));
  view.SetForegroundColor(vtkm::rendering::Color(0.0f, 0.0f, 0.0f));

  view.Paint();

  view.SaveAs("EdgeRendering.ppm");
}

void DoRender()
{
  DoBasicRender();
  DoPointRender();
  DoEdgeRender();
}

} // anonymous namespace

int Rendering(int argc, char* argv[])
{
  return vtkm::cont::testing::Testing::Run(DoRender, argc, argv);
}
