/*
 *  <Short Description>
 *  Copyright (C) 2023  Brett Terpstra
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
#include <blt/gfx/renderer/resource_manager.h>
#include <blt/std/logging.h>
#include <blt/std/thread.h>

namespace blt::gfx
{
    
    void resource_manager::cleanup()
    {
        for (const auto& p : textures_2d)
            delete p.second;
    }
    
    void resource_manager::enqueue(std::string path, std::string name)
    {
        textures_to_load.emplace_back(resource_prefix + std::move(path), std::move(name));
    }
    
    void resource_manager::load_resources(std::size_t threads)
    {
#ifndef __EMSCRIPTEN__
        blt::thread_pool<false> pool{threads, [&]() {
            loadable_texture texture;
            {
                std::scoped_lock lock(load_lock);
                if (textures_to_load.empty())
                    return;
                texture = textures_to_load.back();
                textures_to_load.pop_back();
            }
            BLT_DEBUG("Loading texture file %s", texture.path.c_str());
            auto* file = new texture_file(texture.path, texture.name);
            {
                std::scoped_lock lock(save_lock);
                loaded_textures.push_back(file);
            }
        }};
        do
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            {
                std::scoped_lock lock(load_lock);
                if (textures_to_load.empty())
                    break;
            }
            {
                std::scoped_lock lock(save_lock);
                while (!loaded_textures.empty())
                {
                    auto* back = loaded_textures.back();
                    textures_2d.insert({back->getName(), new texture_gl2D(back->texture())});
                    BLT_DEBUG("Loaded Texture '%s'", back->getName().c_str());
                    delete back;
                    loaded_textures.pop_back();
                }
            }
        } while (true);
#else
        for (const auto& texture : textures_to_load)
        {
            BLT_DEBUG("Loading texture file %s", texture.path.c_str());
            loaded_textures.push_back(new texture_file(texture.path, texture.name));
        }
        textures_to_load.clear();
#endif

#ifndef __EMSCRIPTEN__
        pool.stop();
        while (!pool.complete());
#endif
        while (!loaded_textures.empty())
        {
            auto* back = loaded_textures.back();
            textures_2d.insert({back->getName(), new texture_gl2D(back->texture())});
            BLT_DEBUG("Loaded texture '%s'", back->getName().c_str());
            delete back;
            loaded_textures.pop_back();
        }
    }
}
