#include <pch.hpp>

#include <layer_stack.hpp>
#include <core.hpp>

#include <logging.hpp>

namespace OpenEngine {
    LayerStack::~LayerStack()
    {
        OE_PROFILE_FUNCTION();

        for (auto& layer : layers)
            layer->OnDetach();
    }

    void LayerStack::QueueLayerPush(Ref<Layer> layer)
    {
        layers_to_push.emplace_back(layer);
    }

    void LayerStack::QueueLayerPop(Ref<Layer> layer)
    {
        layers_to_pop.emplace_back(layer);
    }

    void LayerStack::QueueOverlayPush(Ref<Layer> overlay)
    {
        overlay_to_push.emplace_back(overlay);
    }

    void LayerStack::QueueOverlayPop(Ref<Layer> overlay)
    {
        overlay_to_pop.emplace_back(overlay);
    }

    void LayerStack::UpdateLayers()
    {
        OE_PROFILE_FUNCTION();

        {
            OE_PROFILE_SCOPE("Popping Layers");
            // processing pop queue layers
            for (auto& layer : layers_to_pop) {
                auto it = std::find(layers.begin(), layers.begin() + layer_insert_index, layer);
                if (it != layers.end()) {
                    layer->OnDetach();
                    layers.erase(it);
                    layer_insert_index--;
                }
            }

            layers_to_pop.clear();

            // processing pop queue overlays
            for (auto& overlay : overlay_to_pop) {
                auto it = std::find(layers.begin() + layer_insert_index, layers.end(), overlay);
                if (it != layers.end()) {
                    overlay->OnDetach();
                    layers.erase(it);
                }
            }

            overlay_to_pop.clear();
        }


        {
            OE_PROFILE_SCOPE("Pushing Layers");
            // processing push queue layers
            for (auto& layer : layers_to_push) {
                layers.emplace(layers.begin() + layer_insert_index, layer);
                layer_insert_index++;
                layer->OnAttach();
                OE_CORE_DEBUG("Added layer: {}", layer->GetName());
            }

            layers_to_push.clear();

            // processing push queue overlays
            for (auto& overlay : overlay_to_push) {
                layers.emplace_back(overlay);
                overlay->OnAttach();
            }

            overlay_to_push.clear();
        }
    }
}
