#pragma once
#include <c10/cuda/CUDAStream.h>
#include <torch/extension.h>
#include <cstdint>
#include <cassert>
#include <cstdio>
#include <cuda_runtime.h>
#include <memory>
#include "utils.h"
#include "hash/hash.h"


#define CUDA_CHECK(call)                                                       \
{                                                                              \
    const cudaError_t error = call;                                            \
    if (error != cudaSuccess)                                                  \
    {                                                                          \
        fprintf(stderr, "Error: %s:%d, ", __FILE__, __LINE__);                 \
        fprintf(stderr, "code: %d, reason: %s\n", error,                       \
                cudaGetErrorString(error));                                    \
    }                                                                          \
}



#define DISPATCH_GET(strategy, grid, block, smem, stream, ...)                                                          \
{                                                                                                                       \
    switch (strategy){                                                                                                  \
    case CacheConfig::CacheEvictStrategy::LRU:                                                                          \
        GetInternal<KeyType,ElemType,CacheConfig::CacheEvictStrategy::LRU><<<grid, block, smem, stream>>>(__VA_ARGS__); \
        break;                                                                                                          \
    case CacheConfig::CacheEvictStrategy::FIFO:                                                                         \
        GetInternal<KeyType,ElemType,CacheConfig::CacheEvictStrategy::FIFO><<<grid, block, smem, stream>>>(__VA_ARGS__);\
        break;                                                                                                          \
    case CacheConfig::CacheEvictStrategy::LFU:                                                                          \
        GetInternal<KeyType,ElemType,CacheConfig::CacheEvictStrategy::LFU><<<grid, block, smem, stream>>>(__VA_ARGS__); \
        break;                                                                                                          \
    }                                                                                                                   \
}


#define DISPATCH_PUT(strategy, grid, block, smem, stream, ...)                                                                      \
{                                                                                                                                   \
    switch (strategy){                                                                                                              \
    case CacheConfig::CacheEvictStrategy::LRU:                                                                                      \
        PutWithoutEvictInternal<KeyType,ElemType,CacheConfig::CacheEvictStrategy::LRU><<<grid, block, smem, stream>>>(__VA_ARGS__); \
        break;                                                                                                                      \
    case CacheConfig::CacheEvictStrategy::FIFO:                                                                                     \
        PutWithoutEvictInternal<KeyType,ElemType,CacheConfig::CacheEvictStrategy::FIFO><<<grid, block, smem, stream>>>(__VA_ARGS__);\
        break;                                                                                                                      \
    case CacheConfig::CacheEvictStrategy::LFU:                                                                                      \
        PutWithoutEvictInternal<KeyType,ElemType,CacheConfig::CacheEvictStrategy::LFU><<<grid, block, smem, stream>>>(__VA_ARGS__); \
        break;                                                                                                                      \
    }                                                                                                                               \
}


#define DISPATCH_EVICT(strategy, grid, block, smem, stream, ...)                                                          \
{                                                                                                                         \
    switch (strategy){                                                                                                    \
    case CacheConfig::CacheEvictStrategy::LRU:                                                                            \
        EvictInternal<KeyType,ElemType,CacheConfig::CacheEvictStrategy::LRU><<<grid, block, smem, stream>>>(__VA_ARGS__); \
        break;                                                                                                            \
    case CacheConfig::CacheEvictStrategy::FIFO:                                                                           \
        EvictInternal<KeyType,ElemType,CacheConfig::CacheEvictStrategy::FIFO><<<grid, block, smem, stream>>>(__VA_ARGS__);\
        break;                                                                                                            \
    case CacheConfig::CacheEvictStrategy::LFU:                                                                            \
        EvictInternal<KeyType,ElemType,CacheConfig::CacheEvictStrategy::LFU><<<grid, block, smem, stream>>>(__VA_ARGS__); \
        break;                                                                                                            \
    }                                                                                                                     \
}



//#define CAST_CACHE_INT32(c, strategy) \
//{                                         \
//    switch (strategy){                                                                                                    \
//    case CacheConfig::CacheEvictStrategy::LRU:                                                                            \
//        c = reinterpret_cast<LRUCache> \
//        break;                                                                                                            \
//    case CacheConfig::CacheEvictStrategy::FIFO:                                                                           \
//        EvictInternal<KeyType,ElemType,CacheConfig::CacheEvictStrategy::FIFO><<<grid, block, smem, stream>>>(__VA_ARGS__);\
//        break;                                                                                                            \
//    case CacheConfig::CacheEvictStrategy::LFU:                                                                            \
//        EvictInternal<KeyType,ElemType,CacheConfig::CacheEvictStrategy::LFU><<<grid, block, smem, stream>>>(__VA_ARGS__); \
//        break;                                                                                                            \
//    }
//}
//
//
//
//#define CAST_CACHE(c, strategy,is_int32) \
//{                               \
//    if(is_int32){                        \
//        CAST_CACHE_INT32(c,strategy)\
//    }else{                               \
//        CAST_CACHE_INT64(c,strategy)\
//    }\
//}
//





