#include "tile/base/logging.h"
#include "tile/base/object_pool.h"
#include "tile/base/random.h"

namespace tile {

namespace testing {
struct CachedString {
    std::string str;
};
}// namespace testing

template<>
struct PoolTraits<testing::CachedString> {
    static constexpr auto kType                 = PoolType::ThreadLocal;

    static constexpr std::size_t kLowWaterMark  = 16;
    static constexpr std::size_t kHighWaterMark = 128;
    static constexpr auto kMaxIdle              = std::chrono::seconds(10);
};

namespace testing {

template<int min_val = 0, int max_val = 255>
inline void
RandomString(std::string *str, std::size_t min_len = 10000, std::size_t max_len = 100000)
{
    TILE_CHECK_LE(min_len, max_len);

    str->resize(Random(min_len, max_len));
    for (auto &&e : *str) { e = Random(0, 255); }
}

inline std::string
RandomString(std::size_t min_len = 10000, std::size_t max_len = 100000)
{
    TILE_CHECK_LE(min_len, max_len);
    TILE_CHECK_GT(min_len, 0);
    std::string result(Random(min_len, max_len), 0);
    RandomString(&result);
    return result;
}

inline PooledPtr<CachedString>
GetCachedString(std::size_t len = -1)
{
    auto ptr = object_pool::Get<CachedString>();
    if (len != static_cast<std::size_t>(-1)) { ptr->str.resize(len); }
    return ptr;
}

inline PooledPtr<CachedString>
GetCachedRandomString(std::size_t min_len = 100000, std::size_t max_len = 100000)
{
    auto ptr       = object_pool::Get<CachedString>();
    const auto len = ptr->str.size();
    ptr->str.resize(Random(min_len, max_len));
    RandomString(&ptr->str);
    return ptr;
}

}// namespace testing
}// namespace tile
