#pragma once

#include <maps/libs/common/include/exception.h>
#include <yandex/maps/wiki/threadutils/threadpool.h>
#include <map>
#include <memory>
#include <mutex>
#include <queue>

namespace maps::wiki {

class ThreadPools
{
public:
    using ThreadPoolPtr = std::unique_ptr<ThreadPool>;

    class Holder
    {
    public:
        Holder(ThreadPools& pools, ThreadPoolPtr pool)
            : pools_(pools)
            , pool_(std::move(pool))
        {}

        Holder(const Holder&) = delete;
        Holder(Holder&&) = delete;
        Holder& operator=(const Holder&) = delete;
        Holder& operator=(Holder&&) = delete;

        ~Holder()
        {
            pools_.release(std::move(pool_));
        }

        ThreadPool& operator* () { return *pool_; }

    private:
        ThreadPools& pools_;
        ThreadPoolPtr pool_;
    };

    ThreadPools() = default;
    ~ThreadPools() = default;

    ThreadPools(const ThreadPools&) = delete;
    ThreadPools(ThreadPools&&) = delete;
    ThreadPools& operator=(const ThreadPools&) = delete;
    ThreadPools& operator=(ThreadPools&&) = delete;

    Holder pool(size_t threadsNumber);

private:
    void release(ThreadPoolPtr pool);

private:
    std::mutex mutex_;
    std::map<size_t, std::queue<ThreadPoolPtr>> threadsNumberToPools_;
};

} // namespace maps::wiki
