#include "rendererpool.h"
#include "exception.h"
#include "rendererlayerstraverse.h"
#include <maps/libs/log8/include/log8.h>

namespace maps::wiki {

class Logger: public maps::renderer::base::ILogger
{
public:
    MessageType severity() const override
    {
        return ErrorMessage;
    }

    void setSeverity(MessageType) override
    {
    }

    void log(const std::wstring & message, MessageType subject) override
    {
        std::string m;
        m.assign(message.begin(),message.end());
        switch(subject) {
        case ErrorMessage: ERROR() << m; break;
        case WarningMessage: //WARN() << m; break;
        case InfoMessage: //INFO() << m; break;
        case DebugMessage: //DEBUG() << m; break;
        default:
            break;
        }
    }
};

RendererPool::RendererPool(const std::string& mapPath)
    : mapPath_(mapPath)
    , pLogger_(std::make_unique<Logger>())
    , cntAcquired_(0)
{
    auto renderer = createRenderer();

    RendererLayersTraverse layersTraverse;
    renderer->traverse(layersTraverse);
    labeledCategories_ = layersTraverse.labeledCategories();

    renderers_.emplace(std::move(renderer));
}

RendererPool::HolderPtr RendererPool::acquire()
{
    std::lock_guard<std::mutex> lock(rendererListMutex_);
    RendererPtr pRenderer;
    if (renderers_.empty()) {
        pRenderer = createRenderer();
    } else {
        pRenderer.swap(renderers_.front());
        renderers_.pop();
    }
    ++cntAcquired_;
    return std::make_unique<Holder>(*this, std::move(pRenderer));
}

std::string RendererPool::stat() const
{
    std::stringstream ss;
    std::lock_guard<std::mutex> lock(rendererListMutex_);
    ss << " RendererPool stat: size=" << renderers_.size()
       << "; acquired=" << cntAcquired_;
    return ss.str();
}

void RendererPool::release(RendererPtr renderer)
{
    std::lock_guard<std::mutex> lock(rendererListMutex_);
    renderers_.emplace(std::move(renderer));
    --cntAcquired_;
}

RendererPtr RendererPool::createRenderer()
{
    RendererPtr pRenderer(maps::tilerenderer4::createOnlineTileRenderer(pLogger_));
    pRenderer->open(mapPath_);
    return pRenderer;
}

} //namespace maps::wiki
