#pragma once

#include "common.h"

#undef BOOST_HAS_RVALUE_REFS
#include <yandex/maps/tilerenderer4/IOnlineRenderer.h>

#include <memory>
#include <mutex>
#include <queue>

namespace maps::wiki {

// Simple RendererPool to use IOnlineRenderer in multi threads;
// RendererPool used in conjunction with write transaction, so its size depends
// write transaction pool size;
// Single renderer created in _c_tor other cretaed on demand;

using RendererPtr = std::unique_ptr<maps::tilerenderer4::IOnlineRenderer>;

class RendererPool
{
public:
    class Holder
    {
    public:
        Holder(RendererPool& pool, RendererPtr renderer)
            : pool_(pool)
            , renderer_(std::move(renderer))
        {}

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

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

        RendererPtr::element_type* renderer() const
        {
            return renderer_.get();
        }

    private:
        RendererPool& pool_;
        RendererPtr   renderer_;
    };
    using HolderPtr = std::unique_ptr<Holder>;

    explicit RendererPool(const std::string& mapPath);

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

    HolderPtr acquire();

    std::string stat() const;

    const StringSet& labeledCategories() const { return labeledCategories_; }

private:
    void release(RendererPtr renderer);

    RendererPtr createRenderer();

private:
    StringSet labeledCategories_;
    const std::string mapPath_;
    std::queue<RendererPtr> renderers_;
    mutable std::mutex rendererListMutex_;
    maps::renderer::base::ILoggerPtr pLogger_;
    size_t cntAcquired_;
};

} //namespace maps::wiki
