package electrosphere.renderer.pipelines;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import electrosphere.engine.Globals;
import electrosphere.menu.debug.ImGuiWindowMacros;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.ui.imgui.ImGuiWindow;
import imgui.ImGui;
import imgui.extension.implot.ImPlot;
import imgui.gl3.ImGuiImplGl3;
import imgui.glfw.ImGuiImplGlfw;
import imgui.internal.ImGuiContext;

/**
 * ImGui rendering pipeline
 */
public class ImGuiPipeline implements RenderPipeline {

    //
    //imgui related
    //
    //imgui internal objects
    private final ImGuiImplGlfw imGuiGlfw = new ImGuiImplGlfw();
    private final ImGuiImplGl3 imGuiGl13 = new ImGuiImplGl3();

    //the context pointer for the core imgui objects
    private ImGuiContext imGuiContext = null;
    //if set to true, will render imgui windows
    private boolean imGuiShouldRender = true;
    //All imgui windows that should be displayed
    private List<ImGuiWindow> imGuiWindows = new CopyOnWriteArrayList<ImGuiWindow>();

    /**
     * Constructor for the pipeline
     * @param windowId The glfw window id
     * @param glfwVersion the glfw version
     */
    public ImGuiPipeline(long windowId, String glslVersion){
        //init imgui (must happen after gl.createCapabilities)
        imGuiContext = ImGui.createContext();
        if(!imGuiContext.isValidPtr()){
            throw new IllegalStateException("Imgui failed to initialize.");
        }
        ImPlot.createContext();
        imGuiGlfw.init(Globals.window,true);
        imGuiGl13.init(glslVersion);
    }

    @Override
    public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) {
        /**
         * Render imgui
         */
        if(imGuiShouldRender){
            imGuiGlfw.newFrame();
            ImGui.newFrame();
            for(ImGuiWindow window : imGuiWindows){
                window.draw();
            }
            ImGui.render();
            imGuiGl13.renderDrawData(ImGui.getDrawData());
        }
    }


    /**
     * Adds a n imgui window to the pipeline
     * @param window The window
     */
    public void addImGuiWindow(ImGuiWindow window){
        imGuiWindows.add(window);
    }

    /**
     * Removes an imgui window from the pipeline
     * @param window The window
     */
    public void removeImGuiWindow(ImGuiWindow window){
        imGuiWindows.remove(window);
    }

    /**
     * Checks if an imgui window is open that should capture controls
     * @return true if there is a control-capturing window open, false otherwise
     */
    public boolean shouldCaptureControls(){
        for(ImGuiWindow window : imGuiWindows){
            if(window == ImGuiWindowMacros.getMainDebugWindow() && window.isOpen()){
                return true;
            }
        }
        return false;
    }


    
}
