#ifndef TILE_BASE_OBJECT_POOL_THREAD_LOCAL_H
#define TILE_BASE_OBJECT_POOL_THREAD_LOCAL_H

#pragma once
#include "tile/base/demangle.h"
#include "tile/base/erased_ptr.h"
#include "tile/base/object_pool/types.h"

#include <chrono>
#include <deque>

namespace tile {
namespace object_pool {
namespace detail {
namespace tls {
struct TimestampedObject {
    ErasedPtr ptr;
    std::chrono::steady_clock::time_point last_used;
};

struct PoolDescriptor {
    PoolDescriptor(std::size_t low_water_mark, std::size_t high_water_mark, std::chrono::nanoseconds max_idle)
        : low_water_mark(low_water_mark),
          high_water_mark(high_water_mark),
          max_idle(max_idle)
    {}

    const std::size_t low_water_mark;
    const std::size_t high_water_mark;
    std::chrono::nanoseconds max_idle;
    std::chrono::steady_clock::time_point last_wash{std::chrono::steady_clock::now()};

    std::deque<TimestampedObject> primary_cache;
    std::deque<TimestampedObject> secondary_cache;
};

template<typename T>
PoolDescriptor *
GetThradLocalPool()
{
    static_assert(PoolTraits<T>::kHighWaterMark > PoolTraits<T>::kLowWaterMark,
                  "You should leave some room between the water marks.");
    constexpr auto kEffectiveHighWaterMark = PoolTraits<T>::kHighWaterMark - PoolTraits<T>::kLowWaterMark;
    static thread_local PoolDescriptor pool =
        PoolDescriptor(PoolTraits<T>::kLowWaterMark, PoolTraits<T>::kHighWaterMark, PoolTraits<T>::kMaxIdle);

    TILE_DCHECK((pool.low_water_mark == PoolTraits<T>::kLowWaterMark)
                    && (pool.high_water_mark == PoolTraits<T>::kHighWaterMark)
                    && (pool.max_idle == PoolTraits<T>::kMaxIdle),
                "You likely had am ODR-violation when customizing type [{}]", GetTypeName<T>());
    return &pool;
}

void *Get(const TypeDescriptor &desc, PoolDescriptor *pool);
void Put(const TypeDescriptor &desc, PoolDescriptor *pool, void *ptr);

}// namespace tls
}// namespace detail
}// namespace object_pool
}// namespace tile

#endif// TILE_BASE_OBJECT_POOL_THREAD_LOCAL_H
