#pragma once 

#include <cstdint>
namespace gpucache {

    struct CacheConfig {
        enum CacheEvictStrategy {
            FIFO,
            LRU,
            LFU
        };
        CacheConfig() = default;
        CacheConfig(CacheEvictStrategy s, uint64_t cap, uint32_t key_size, uint32_t value_size, uint32_t max_query_num, int8_t device_id, uint32_t dim):strategy(s),
            capacity(cap),keySize(key_size),valueSize(value_size),maxQueryNum(max_query_num),deviceId(device_id),dim(dim){}
        CacheEvictStrategy strategy;
        uint64_t capacity;
        uint32_t keySize;
        uint32_t valueSize;
        uint32_t dim;
        uint32_t maxQueryNum;
        int8_t deviceId;
    };

// Cache Interface
    template<typename KeyType, typename ElemType>
    class Cache {
    public:

        Cache() = default;

        virtual ~Cache() = default;

        virtual uint32_t KeySize() = 0;

        virtual uint32_t ValueSize() = 0;

        virtual CacheConfig::CacheEvictStrategy Strategy() = 0;

        virtual uint64_t Capacity() = 0;

        virtual uint32_t NumElemsPerValue() = 0;

        virtual int8_t DeviceId() = 0;

        virtual uint32_t Dim() = 0;

        virtual void Get(cudaStream_t stream, uint32_t num_keys, KeyType *keys, ElemType *values, bool* find_mask) = 0;

        virtual void Put(cudaStream_t stream, uint32_t num_keys, KeyType *keys, ElemType *values,uint32_t *n_evict, KeyType* evict_keys) = 0;


        // virtual void* Mutex() = 0;

        virtual void Clear() = 0;

        virtual uint32_t MaxQueryNum() = 0;
    };


}
