#include <stdlib.h>
#include <string.h>
#include <CL/OpenCL.h>


cl_platform_id s_clSelectedPlatformID = NULL;
cl_uint s_ciDeviceCount = 0;
cl_uint s_device = 0;
cl_device_id* s_devices = NULL;
cl_context s_cxGPUContext;

cl_int GetPlatform()
{
	char chBuffer[1024];
    cl_uint num_platforms;
    cl_platform_id* clPlatformIDs;
    cl_int ciErrNum;
    
	
    // Get OpenCL platform count
    ciErrNum = clGetPlatformIDs (0, NULL, &num_platforms);
    if (ciErrNum != CL_SUCCESS)
    {
        //shrLog(" Error %i in clGetPlatformIDs Call !!!\n\n", ciErrNum);
        return -1000;
    }
    else
    {
        if(num_platforms == 0)
        {
            //shrLog("No OpenCL platform found!\n\n");
            return -2000;
        }
        else
        {
            // if there's a platform or more, make space for ID's
            if ((clPlatformIDs = (cl_platform_id*)malloc(num_platforms * sizeof(cl_platform_id))) == NULL)
            {
                //shrLog("Failed to allocate memory for cl_platform ID's!\n\n");
                return -3000;
            }

            // get platform info for each platform and trap the NVIDIA platform if found
            ciErrNum = clGetPlatformIDs (num_platforms, clPlatformIDs, NULL);
            for(cl_uint i = 0; i < num_platforms; ++i)
            {
                ciErrNum = clGetPlatformInfo (clPlatformIDs[i], CL_PLATFORM_NAME, 1024, &chBuffer, NULL);
                if(ciErrNum == CL_SUCCESS)
                {
					if(strstr(chBuffer, "Intel") != NULL)
                    {
                    	s_clSelectedPlatformID = clPlatformIDs[i];
                        break;
                    }
                }
            }

            // default to zeroeth platform if NVIDIA not found
            if(s_clSelectedPlatformID == NULL)
            {
                //shrLog("WARNING: NVIDIA OpenCL platform not found - defaulting to first platform!\n\n");
            	s_clSelectedPlatformID = clPlatformIDs[0];
            }

            free(clPlatformIDs);
        }
    }

	return CL_SUCCESS;
}

cl_int GetDevices() {
	cl_int ciErrNum = clGetDeviceIDs (s_clSelectedPlatformID, CL_DEVICE_TYPE_CPU, 0, NULL, &s_ciDeviceCount);
	if (ciErrNum != CL_SUCCESS)
	{
		//shrLog(" Error %i in clGetDeviceIDs call !!!\n\n", ciErrNum);
		return ciErrNum;
	}
	else if (s_ciDeviceCount == 0)
	{
		//shrLog(" There are no devices supporting OpenCL (return code %i)\n\n", ciErrNum);
		return ciErrNum;
	}

	s_devices = (cl_device_id*) malloc(sizeof(cl_device_id) * s_ciDeviceCount);
	ciErrNum = clGetDeviceIDs (s_clSelectedPlatformID, CL_DEVICE_TYPE_CPU, s_ciDeviceCount, s_devices, &s_ciDeviceCount);
	s_device = 0;


	return ciErrNum;
}

cl_int CreateContext() {
	cl_int clerr;
	s_cxGPUContext = clCreateContext(0, 1, &(s_devices[s_device]), NULL, NULL, &clerr);
	if (s_cxGPUContext == (cl_context)0)
	{
		//shrLog("Failed to create OpenCL context!\n");
		return -11000;
	}

	return CL_SUCCESS;
}

int main(int argc, char** argv)
{
	GetPlatform();
	GetDevices();
	CreateContext();

	return 0;
}