package electrosphere.menu.debug;

import java.util.HashMap;
import java.util.Map;

import electrosphere.controls.ControlHandler.ControlsState;
import electrosphere.engine.Globals;
import electrosphere.renderer.ui.imgui.ImGuiLinePlot;
import electrosphere.renderer.ui.imgui.ImGuiWindow;
import electrosphere.renderer.ui.imgui.ImGuiLinePlot.ImGuiLinePlotDataset;
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
import electrosphere.server.fluid.manager.ServerFluidManager;
import imgui.ImGui;

/**
 * Various methods for creating specific imgui windows in engine
 */
public class ImGuiWindowMacros {
    

    //main debug menu
    private static ImGuiWindow mainDebugWindow;


    //Framerate graph
    private static ImGuiWindow globalFrametimeWindow;
    private static ImGuiLinePlot globalFrametimePlot;
    private static Map<String,ImGuiLinePlotDataset> globalFrametimeDatasets;

    //fluid details
    private static ImGuiWindow fluidWindow;

    /**
     * Initializes imgui windows
     */
    public static void initImGuiWindows(){
        createMainDebugMenu();
        createFramerateGraph();
        ImGuiPlayerEntity.createPlayerEntityDebugWindow();
        createFluidDebugWindow();
        ImGuiEntityMacros.createClientEntityWindows();
        ImGuiUIFramework.createUIFrameworkWindows();
        ImGuiControls.createControlsWindows();
        ImGuiAI.createAIDebugWindow();
        ImGuiAudio.createAudioDebugMenu();
    }

    /**
     * Creates a framerate graph
     */
    private static void createFramerateGraph(){
        globalFrametimeWindow = new ImGuiWindow("Frametime Graph");
        globalFrametimePlot = new ImGuiLinePlot("Frametime plot");
        globalFrametimeDatasets = new HashMap<String,ImGuiLinePlotDataset>();
        initFramerateGraphSeries("totalframerate");
        initFramerateGraphSeries("serversim");
        initFramerateGraphSeries("clientsim");
        initFramerateGraphSeries("render");
        initFramerateGraphSeries("assetLoad");
        initFramerateGraphSeries("clientNetwork");
        initFramerateGraphSeries("controls");
        globalFrametimeWindow.addElement(globalFrametimePlot);
        globalFrametimeWindow.setOpen(false);
        Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(globalFrametimeWindow);
    }

    /**
     * Gets the main debug window
     * @return the main debug window
     */
    public static ImGuiWindow getMainDebugWindow(){
        return mainDebugWindow;
    }

    /**
     * Inits a series for the framerate graph
     * @param seriesName The name of the series
     */
    private static void initFramerateGraphSeries(String seriesName){
        ImGuiLinePlotDataset dataSet = new ImGuiLinePlotDataset(seriesName, 50);
        globalFrametimeDatasets.put(seriesName,dataSet);
        for(int x = 0; x < 50; x++){
            dataSet.addPoint(x, 0);
        }
        globalFrametimePlot.addDataset(dataSet);
    }

    /**
     * Adds a datapoint to the framerate graph
     * @param seriesName The name of the series to add a datapoint for
     * @param y the y coord
     */
    public static void addGlobalFramerateDatapoint(String seriesName, double y){
        if(globalFrametimeDatasets != null && globalFrametimeDatasets.containsKey(seriesName)){
            globalFrametimeDatasets.get(seriesName).addPoint(y);
        }
    }

    /**
     * Create fluid debug menu
     */
    private static void createFluidDebugWindow(){
        fluidWindow = new ImGuiWindow("Fluids");
        fluidWindow.setCallback(new ImGuiWindowCallback() {
            @Override
            public void exec() {
                //audio engine details
                ImGui.text("Fluids Debug");
                if(ImGui.button("Toggle Simulation")){
                    ServerFluidManager fluidManager = Globals.playerManager.getPlayerRealm(Globals.clientPlayer).getServerWorldData().getServerFluidManager();
                    fluidManager.setSimulate(!fluidManager.getSimulate());
                }
            }
        });
        fluidWindow.setOpen(false);
        Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(fluidWindow);
    }


    /**
     * Inits the main debug menu
     */
    private static void createMainDebugMenu(){
        mainDebugWindow = new ImGuiWindow("Debug");
        mainDebugWindow.setCallback(new ImGuiWindowCallback() {
            @Override
            public void exec() {
                //show global framerate line graph
                if(ImGui.button("Show Overall Frametime")){
                    globalFrametimeWindow.setOpen(true);
                }
                //show audio debug
                if(ImGui.button("Show Audio Debug Menu")){
                    ImGuiAudio.audioDebugMenu.setOpen(true);
                }
                //show audio debug
                if(ImGui.button("Show Player Entity Debug Menu")){
                    ImGuiPlayerEntity.playerEntityWindow.setOpen(true);
                }
                //show fluids debug
                if(ImGui.button("Show Fluids Debug Menu")){
                    fluidWindow.setOpen(true);
                }
                //client entity debug
                if(ImGui.button("Client Entity Debug")){
                    ImGuiEntityMacros.clientEntityListWindow.setOpen(true);
                }
                //controls state debug
                if(ImGui.button("Control State Debug")){
                    ImGuiControls.controlsWindow.setOpen(true);
                }
                //controls state debug
                if(ImGui.button("AI State Debug")){
                    ImGuiAI.aiWindow.setOpen(true);
                }
                //close button
                if(ImGui.button("Close")){
                    mainDebugWindow.setOpen(false);
                }
            }
        });
        mainDebugWindow.setOpen(false);
        Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(mainDebugWindow);
    }

    /**
     * Toggles the open state of the menu
     */
    public static void toggleMainDebugMenu(){
        mainDebugWindow.setOpen(!mainDebugWindow.isOpen());
        if(mainDebugWindow.isOpen()){
            Globals.controlHandler.hintUpdateControlState(ControlsState.IN_GAME_MAIN_MENU);
        } else {
            Globals.controlHandler.hintUpdateControlState(ControlsState.MAIN_GAME);
        }
    }

}
