#include <vtkm/cont/RuntimeDeviceTracker.h>

#include <vtkm/cont/ArrayCopy.h>

#include <vtkm/cont/cuda/DeviceAdapterCuda.h>

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

namespace
{

static const vtkm::Id ARRAY_SIZE = 10;

void CopyWithRuntime()
{
  std::cout << "Checking runtime in copy." << std::endl;

  using T = vtkm::Float32;
  vtkm::cont::ArrayHandle<T> srcArray;
  srcArray.Allocate(ARRAY_SIZE);
  SetPortal(srcArray.GetPortalControl());

  vtkm::cont::ArrayHandle<T> destArray;

  ////
  //// BEGIN-EXAMPLE RestrictCopyDevice.cxx
  ////
  vtkm::cont::RuntimeDeviceTracker tracker;
  tracker.DisableDevice(vtkm::cont::DeviceAdapterTagCuda());

  vtkm::cont::ArrayCopy(srcArray, destArray, tracker);
  ////
  //// END-EXAMPLE RestrictCopyDevice.cxx
  ////

  VTKM_TEST_ASSERT(destArray.GetNumberOfValues() == ARRAY_SIZE, "Bad array size.");
  CheckPortal(destArray.GetPortalConstControl());
}

void ChangeDefaultRuntime()
{
  std::cout << "Checking changing default runtime." << std::endl;

  ////
  //// BEGIN-EXAMPLE ForceGlobalDevice.cxx
  ////
  vtkm::cont::GetGlobalRuntimeDeviceTracker().ForceDevice(
    vtkm::cont::DeviceAdapterTagSerial());
  ////
  //// END-EXAMPLE ForceGlobalDevice.cxx
  ////

  ////
  //// BEGIN-EXAMPLE ResetGlobalDevice.cxx
  ////
  vtkm::cont::GetGlobalRuntimeDeviceTracker().Reset();
  ////
  //// END-EXAMPLE ResetGlobalDevice.cxx
  ////
}

void Run()
{
  CopyWithRuntime();
  ChangeDefaultRuntime();
}

} // anonymous namespace

int RuntimeDeviceTracker(int, char* [])
{
  return vtkm::cont::testing::Testing::Run(Run);
}
