//
// Copyright (c) 2017 The Khronos Group Inc.
// 
// 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
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// 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.
//
#include "utils.h"

int get_device_ids(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements,
                   cl_dx9_media_adapter_type_khr adapterType)
{
  CResult result;

  std::auto_ptr<CDeviceWrapper> deviceWrapper;
  if (!DeviceCreate(adapterType, deviceWrapper))
  {
    result.ResultSub(CResult::TEST_ERROR);
    return result.Result();
  }

  cl_uint devicesExpectedNum = 0;
  cl_int error = clGetDeviceIDs(gPlatformIDdetected, CL_DEVICE_TYPE_ALL, 0, 0, &devicesExpectedNum);
  if (error != CL_SUCCESS || devicesExpectedNum < 1)
  {
    log_error("clGetDeviceIDs failed: %s\n", IGetErrorString(error));
    result.ResultSub(CResult::TEST_FAIL);
    return result.Result();
  }

  std::vector<cl_device_id> devicesExpected(devicesExpectedNum);
  error = clGetDeviceIDs(gPlatformIDdetected, CL_DEVICE_TYPE_ALL, devicesExpectedNum, &devicesExpected[0], 0);
  if (error != CL_SUCCESS)
  {
    log_error("clGetDeviceIDs failed: %s\n", IGetErrorString(error));
    result.ResultSub(CResult::TEST_FAIL);
    return result.Result();
  }

  while (deviceWrapper->AdapterNext())
  {
    std::vector<cl_dx9_media_adapter_type_khr> mediaAdapterTypes;
    mediaAdapterTypes.push_back(adapterType);

    std::vector<void *> mediaDevices;
    mediaDevices.push_back(deviceWrapper->Device());

    //check if the test can be run on the adapter
    if (CL_SUCCESS != (error = deviceExistForCLTest(gPlatformIDdetected, adapterType, deviceWrapper->Device(), result)))
    {
      return result.Result();
    }

    cl_uint devicesAllNum = 0;
    error = clGetDeviceIDsFromDX9MediaAdapterKHR(gPlatformIDdetected, 1, &mediaAdapterTypes[0], &mediaDevices[0],
      CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 0, 0, &devicesAllNum);
    if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND)
    {
      log_error("clGetDeviceIDsFromDX9MediaAdapterKHR failed: %s\n", IGetErrorString(error));
      result.ResultSub(CResult::TEST_FAIL);
      return result.Result();
    }

    std::vector<cl_device_id> devicesAll;
    if (devicesAllNum > 0)
    {
      devicesAll.resize(devicesAllNum);
       error = clGetDeviceIDsFromDX9MediaAdapterKHR(gPlatformIDdetected, 1, &mediaAdapterTypes[0], &mediaDevices[0],
        CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, devicesAllNum, &devicesAll[0], 0);
      if (error != CL_SUCCESS)
      {
        log_error("clGetDeviceIDsFromDX9MediaAdapterKHR failed: %s\n", IGetErrorString(error));
        result.ResultSub(CResult::TEST_FAIL);
        return result.Result();
      }
    }

    cl_uint devicesPreferredNum = 0;
    error = clGetDeviceIDsFromDX9MediaAdapterKHR(gPlatformIDdetected, 1, &mediaAdapterTypes[0], &mediaDevices[0],
      CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 0, 0, &devicesPreferredNum);
    if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND)
    {
      log_error("clGetDeviceIDsFromDX9MediaAdapterKHR failed: %s\n", IGetErrorString(error));
      result.ResultSub(CResult::TEST_FAIL);
      return result.Result();
    }

    std::vector<cl_device_id> devicesPreferred;
    if (devicesPreferredNum > 0)
    {
      devicesPreferred.resize(devicesPreferredNum);
      error = clGetDeviceIDsFromDX9MediaAdapterKHR(gPlatformIDdetected, 1, &mediaAdapterTypes[0], &mediaDevices[0],
        CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, devicesPreferredNum, &devicesPreferred[0], 0);
      if (error != CL_SUCCESS)
      {
        log_error("clGetDeviceIDsFromDX9MediaAdapterKHR failed: %s\n", IGetErrorString(error));
        result.ResultSub(CResult::TEST_FAIL);
        return result.Result();
      }
    }

    if (devicesAllNum < devicesPreferredNum)
    {
      log_error("Invalid number of preferred devices. It should be a subset of all devices\n");
      result.ResultSub(CResult::TEST_FAIL);
    }

    for (cl_uint i = 0; i < devicesPreferredNum; ++i)
    {
      cl_uint j = 0;
      for (; j < devicesAllNum; ++j)
      {
        if (devicesPreferred[i] == devicesAll[j])
          break;
      }

      if (j == devicesAllNum)
      {
        log_error("Preferred device is not a subset of all devices\n");
        result.ResultSub(CResult::TEST_FAIL);
      }
    }

    for (cl_uint i = 0; i < devicesAllNum; ++i)
    {
      cl_uint j = 0;
      for (; j < devicesExpectedNum; ++j)
      {
        if (devicesAll[i] == devicesExpected[j])
          break;
      }

      if (j == devicesExpectedNum)
      {
        log_error("CL_ALL_DEVICES_FOR_MEDIA_ADAPTER_KHR should be a subset of all devices for selected platform\n");
        result.ResultSub(CResult::TEST_FAIL);
      }
    }
  }

  if (deviceWrapper->Status() != DEVICE_PASS)
  {
    std::string adapterName;
    AdapterToString(adapterType, adapterName);
    if (deviceWrapper->Status() == DEVICE_FAIL)
  {
      log_error("%s init failed\n", adapterName.c_str());
    result.ResultSub(CResult::TEST_FAIL);
    }
    else
    {
      log_error("%s init incomplete due to unsupported device\n", adapterName.c_str());
      result.ResultSub(CResult::TEST_NOTSUPPORTED);
    }
  }

  return result.Result();
}

int test_get_device_ids(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
  CResult result;

#if defined(_WIN32)
  if(get_device_ids(deviceID, context, queue, num_elements, CL_ADAPTER_D3D9_KHR) != 0)
  {
    log_error("\nTest case (D3D9) failed\n\n");
    result.ResultSub(CResult::TEST_FAIL);
  }

  if(get_device_ids(deviceID, context, queue, num_elements, CL_ADAPTER_D3D9EX_KHR) != 0)
  {
    log_error("\nTest case (D3D9EX) failed\n\n");
    result.ResultSub(CResult::TEST_FAIL);
  }

  if(get_device_ids(deviceID, context, queue, num_elements, CL_ADAPTER_DXVA_KHR) != 0)
  {
    log_error("\nTest case (DXVA) failed\n\n");
    result.ResultSub(CResult::TEST_FAIL);
  }

#else
  return TEST_NOT_IMPLEMENTED;
#endif

  return result.Result();
}
