#pragma once

#define CL_USE_DEPRECATED_OPENCL_2_0_APIS
#ifdef __linux__
#include "cl.h"
#else
#include "CL/cl.h"
#endif

#include "stdint.h"
#include "resolution.h"
#include "debugprinter.h"

#include <QMap>
#include <QStringList>

int maincl(resolution res,uint32_t *destPixel,bool useGpu = true);

class clKernelConfig
{
public:

    clKernelConfig()
    {
        m_name = "";
        m_kernel = NULL;
        m_workSize0=0;
        m_workSize1=0;
    }

    clKernelConfig(QString name,size_t workSize0,size_t workSize1)
    {
        m_name = name;
        m_kernel = NULL;
        m_workSize0=workSize0;
        m_workSize1=workSize1;
    }

    void setKernel(cl_kernel kernel)
    {
        m_kernel = kernel;
    }

    cl_kernel getKernel()
    {
        return m_kernel;
    }

    QString getName() const
    {
        return m_name;
    }

    size_t getWorkSize(int i)
    {
        switch(i)
        {
            case 0: return m_workSize0;
            case 1: return m_workSize1;
        }

        return 0;
    }

private:

    QString m_name;
    cl_kernel m_kernel;
    size_t m_workSize0,m_workSize1;
};

class clWorker : public IPrint
{
public: clWorker(resolution res,bool useGpu = true);
        virtual ~clWorker();

        bool init(uint32_t *workBuffer,uint32_t workBufferLength,QList<clKernelConfig> kernelConfigs);
        bool run(unsigned int sliderX,unsigned int sliderY,unsigned int sliderZ,QString kernelName);
        bool copyBack(uint32_t *outData);
        bool cleanup();
        bool writeWorkBuffer(uint32_t *workBuffer,uint32_t workBufferLength);
        bool clearOutputBuffer();

protected:
        const char *getErrorString(cl_int error);

private:
    resolution m_resolution;
    bool m_useGpu;

    cl_context              m_context;
    cl_command_queue        m_commandQueue;
    cl_device_id            *m_devices;
    QList<clKernelConfig>   m_kernels;
    cl_mem                  m_workBuffer;
    cl_mem                  m_outputBuffer;
    cl_mem                  m_inputImage;
    cl_sampler              m_inputImageSampler;
    cl_program              m_program;
};

