// /*
//  *
//  * ScreenManager
//  *
//  * This is the screen manager for the global screen handler of `TreeHandler` type
//  * Please note: `TreeHandler` is suited for a more broad range of things; however
//  * its initial implementation is for the skill tree. It will be renamed to a more
//  * generic name so this class is more obviously re-usable after its implementation
//  * is complete AND we verify this class can be made more generic for it. Since this
//  * is unknown, it will remain the name it has currently.
//  *
//  *
// */

// package jesse.keeblarcraft.gui;

// import java.lang.reflect.InvocationTargetException;
// import java.util.ArrayList;
// import java.util.HashMap;
// import java.util.List;
// import java.util.Map.Entry;

// import jesse.keeblarcraft.Keeblarcraft;
// import jesse.keeblarcraft.GuiMgr.TreeHandler;
// import net.minecraft.client.MinecraftClient;
// import net.minecraft.client.gui.DrawContext;
// import net.minecraft.client.gui.screen.Screen;
// import net.minecraft.client.gui.screen.ingame.HandledScreen;
// import net.minecraft.entity.player.PlayerInventory;
// import net.minecraft.text.Text;

// // Client side renderer
// public class ScreenManager extends HandledScreen<TreeHandler> {
//     private static ScreenManager static_inst;
//     @SuppressWarnings("resource")
//     private static PlayerInventory static_inventory = new PlayerInventory(null);// = MinecraftClient.getInstance().player.getInventory();

//     public static ScreenManager GetInstance() {
//         if (static_inst == null) {
//             static_inst = new ScreenManager(Keeblarcraft.TREE_HANDLER.create(0, static_inventory), static_inventory, Text.of("Test"));
//         }
//         return static_inst;
//     }

//     private static HashMap<Integer, ArrayList<Class<? extends GenericLayerT>>> layerMap = new HashMap<Integer, ArrayList<Class<? extends GenericLayerT>>>();
//     private static HashMap<Integer, ArrayList<GenericLayerT>> layers = new HashMap<Integer, ArrayList<GenericLayerT>>(); // key: layer id; value: list of classes to draw

//     // private TreeWidget treeWidget = null;
//     private Screen parent;

//     /////////////////////////////////////////////////////////////////////////////
//     /// @fn         ScreenManager
//     ///
//     /// @arg[in]    handler is the TreeHandler (ScreenHandler) object
//     ///
//     /// @arg[in]    inventory is the players inventory. Required by HandledScreen
//     ///             object however is unused currently in this Screen
//     ///
//     /// @arg[in]    title is the title of the screen window
//     ///
//     /// @brief      Class constructor
//     /////////////////////////////////////////////////////////////////////////////
//     public ScreenManager(TreeHandler handler, PlayerInventory inventory, Text title) {
//         super(handler, inventory, title);
//         System.out.println("Called constructor of screen manager!");

//         // Initialize layers in map
//         // for (int i = 0; i < NUMBER_DRAW_LAYERS; i++) {
//         //     layers.put(i, new ArrayList<Class<? extends GenericLayerT>>());
//         // }
//     }

//     /////////////////////////////////////////////////////////////////////////////
//     /// @fn         AddParent
//     ///
//     /// @arg[in]    parent is the parent screen object
//     ///
//     /// @brief      Add a parent screen to the screen object. This is useful if
//     ///             you want to return to the previous screen when this one gets
//     ///             closed by the user
//     /////////////////////////////////////////////////////////////////////////////
//     public void AddParent(Screen parent) {
//         this.parent = parent;
//     }

//     public static void AddWidget(Class<? extends GenericLayerT> widget, int drawLayer) {
//         if (layerMap.containsKey(drawLayer)) {
//             // Just append the widget to the draw layer
//             var layerList = layerMap.get(drawLayer);
//             layerList.add(widget);
//         } else {
//             // Brand new layer!
//             layerMap.put(drawLayer, new ArrayList<>(List.of(widget)));
//         }
//     }

//     /////////////////////////////////////////////////////////////////////////////
//     /// @fn         init
//     ///
//     /// @brief      Initialize method; called one-time to setup class variables
//     /////////////////////////////////////////////////////////////////////////////
//     @Override
//     public void init() {
//         // initialize screen size to the global background picture
//         this.width = MinecraftClient.getInstance().getWindow().getScaledWidth();
//         this.height = MinecraftClient.getInstance().getWindow().getScaledHeight();

//         // Let's go through and initialize all the screen types now in our active memory
//         for (Entry<Integer, ArrayList<Class<? extends GenericLayerT>>> layerEntry : layerMap.entrySet()) {
//             var layerList = layerEntry.getValue();

//             layers.put(layerEntry.getKey(), new ArrayList<>());
//             var activeLayerList = layers.get(layerEntry.getKey());
//             for (int i = 0; i < layerList.size(); i++) {
//                 try {
//                     System.out.println("Attempting to initialize widget with information: LAYER I-VAL W H: " + layerEntry.getKey() + " " + i + " " + this.width + " " + this.height);
//                     GenericLayerT initializedWidget = layerList.get(i).getDeclaredConstructor(int.class, int.class, int.class, int.class, Text.class).newInstance(0, 0, this.width, this.height, Text.of(""));
//                     activeLayerList.add(initializedWidget);
//                 } catch (InstantiationException e) {
//                     System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of IntantiationException");
//                     e.printStackTrace();
//                 } catch (IllegalAccessException e) {
//                     System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of IllegalAccessException");
//                     e.printStackTrace();
//                 } catch (IllegalArgumentException e) {
//                     System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of IllegalArgumentException");
//                     e.printStackTrace();
//                 } catch (InvocationTargetException e) {
//                     System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of InvocationTargetException");
//                     e.printStackTrace();
//                 } catch (NoSuchMethodException e) {
//                     System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of NoSuchMethodException");
//                     e.printStackTrace();
//                 } catch (SecurityException e) {
//                     System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of SecurityException");
//                     e.printStackTrace();
//                 }
//             }
//         }


//         // Initialize child widgets with correct screen values so they can draw themselves in the right area on the screen (duh!)
//         // treeWidget = new TreeWidget(GLOBAL_SCREEN_START_X + 24, GLOBAL_SCREEN_START_Y + 24, GLOBAL_SCREEN_WIDTH - 24, GLOBAL_SCREEN_HEIGHT - 24);
//         // this.addDrawableChild(treeWidget);
//     }

//     /////////////////////////////////////////////////////////////////////////////
//     /// @fn         render
//     ///
//     /// @arg[in]    context is the drawing context of super class
//     ///
//     /// @arg[in]    mouseX is passed to parent class but unused here
//     ///
//     /// @arg[in]    mouseY is passed to parent class but unused here
//     ///
//     /// @brief      Render is called every frame while the screen is open
//     ///
//     /// @note       This is a pure abstract in parent and is required
//     /////////////////////////////////////////////////////////////////////////////
//     @Override
//     public void render(DrawContext context, int mouseX, int mouseY, float delta) {
//         super.render(context, mouseX, mouseY, delta); // This takes care of calling drawBackground which calls DrawMainScreen
//     }

//     /////////////////////////////////////////////////////////////////////////////
//     /// @fn         drawForeground
//     ///
//     /// @arg[in]    context is the drawing context of super class
//     ///
//     /// @arg[in]    mouseX is unused
//     ///
//     /// @arg[in]    mouseY is unused
//     ///
//     /// @brief      Draw foreground exists to draw the titles; however we
//     ///             intentionally override it so the superclass object does not
//     ///             draw the overlay over the background screen
//     /////////////////////////////////////////////////////////////////////////////
//     @Override
//     public void drawForeground(DrawContext context, int mouseX, int mouseY) {
//         // We override this function to intentionally do nothing
//         // If in the future we want, we would draw the foreground and TITLES with this!
//     }

//     /////////////////////////////////////////////////////////////////////////////
//     /// @fn         close
//     ///
//     /// @brief      Called when the screen closes
//     ///
//     /// @note       This is a pure abstract in parent and is required
//     /////////////////////////////////////////////////////////////////////////////
//     @Override
//     public void close() {
//         this.client.setScreen(parent); // return to previous screen or null
//     }

//     /////////////////////////////////////////////////////////////////////////////
//     /// @fn         mouseDragged
//     ///
//     /// @arg[in]    mouseX is x-axis position of original mouse click
//     ///
//     /// @arg[in]    mouseY is y-axis position of original mouse click
//     ///
//     /// @arg[in]    button is the int value of button pressed for mouse dragging
//     ///
//     /// @arg[in]    deltaX is the change in the X position from the previous
//     ///             mouse click
//     ///
//     /// @arg[in]    deltaY is the change in the Y position from the previous
//     ///             mouse click
//     ///
//     /// @brief      The drag event is called on all widgets on the screen so
//     ///             long as the initial position of the drag is within the
//     ///             bounds of the widget box itself. Widgets themselves will need
//     ///             to handle any sub-widgets since the bound check is only
//     ///             there to verify if the event happened ANYWHERE within a
//     ///             widget box
//     /////////////////////////////////////////////////////////////////////////////
//     @Override
//     public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
//         super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
//         // UpdateAnchorValues();

//         for (Entry<Integer, ArrayList<GenericLayerT>> layerEntry : layers.entrySet()) {
//             var layerList = layerEntry.getValue();

//             for (var layerListIterator = 0; layerListIterator < layerList.size(); layerListIterator++) {
//                 var layer = layerList.get(layerListIterator);

//                 // Check to make sure scroll is within the context of the widget then deliver information
//                 if (InBounds(layer.startX, layer.startY, layer.endX, layer.endY, (int) mouseX, (int) mouseY)) {
//                     layer.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
//                 }
//             }
//         }
//         return true;
//     }

//     /////////////////////////////////////////////////////////////////////////////
//     /// @fn         mouseScrolled
//     ///
//     /// @arg[in]    mouseX is the initial X position of the cursor on a scroll
//     ///
//     /// @arg[in]    mouseY is the initial Y position of the cursor on a scroll
//     ///
//     /// @arg[in]    amount is a normalized value that indicates scroll direction
//     ///
//     /// @brief      The scroll event is called on all widgets on the screen so
//     ///             long as the initial position of the scroll is within the
//     ///             bounds of the widget box itself. Widgets themselves will need
//     ///             to handle any sub-widgets since the bound check is only
//     ///             there to verify if the event happened ANYWHERE within a
//     ///             widget box
//     ///
//     /////////////////////////////////////////////////////////////////////////////
//     @Override
//     public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
//         super.mouseScrolled(mouseX, mouseY, amount);

//         for (Entry<Integer, ArrayList<GenericLayerT>> layerEntry : layers.entrySet()) {
//             var layerList = layerEntry.getValue();

//             for (var layerListIterator = 0; layerListIterator < layerList.size(); layerListIterator++) {
//                 var layer = layerList.get(layerListIterator);

//                 // Check to make sure scroll is within the context of the widget then deliver information
//                 if (InBounds(layer.startX, layer.startY, layer.endX, layer.endY, (int) mouseX, (int) mouseY)) {
//                     layer.mouseScrolled(mouseX, mouseY, amount);
//                 }
//             }
//         }
//         return true; // The parent function defines this to be boolean; but I have no idea when I would want to return false from this
//     }

//     /////////////////////////////////////////////////////////////////////////////
//     /// @fn         mouseClicked
//     ///
//     /// @arg[in]    mouseX is the initial X position of the mouse click event
//     ///
//     /// @arg[in]    mouseY is the initial Y position of the mouse click event
//     ///
//     /// @arg[in]    button is the mouse click button (left/right click value)
//     ///
//     /// @brief      The mouse click is called on all widgets on the screen so
//     ///             long as the initial position of the click is within the
//     ///             bounds of the widget box itself. Widgets themselves will need
//     ///             to handle any sub-widgets since the bound check is only
//     ///             there to verify if the event happened ANYWHERE within a
//     ///             widget box
//     ///
//     /////////////////////////////////////////////////////////////////////////////
//     @Override
//     public boolean mouseClicked(double mouseX, double mouseY, int button) {
//         super.mouseClicked(mouseX, mouseY, button);

//         for (Entry<Integer, ArrayList<GenericLayerT>> layerEntry : layers.entrySet()) {
//             var layerList = layerEntry.getValue();

//             for (var layerListIterator = 0; layerListIterator < layerList.size(); layerListIterator++) {
//                 var layer = layerList.get(layerListIterator);

//                 // Check to make sure scroll is within the context of the widget then deliver information
//                 if (InBounds(layer.startX, layer.startY, layer.endX, layer.endY, (int) mouseX, (int) mouseY)) {
//                     layer.mouseClicked(mouseX, mouseY, button);
//                 }
//             }
//         }
//         return true;
//     }

//     /////////////////////////////////////////////////////////////////////////////
//     /// @fn         DrawLayers
//     ///
//     /// @arg[in]    context is the global drawing context for the screen
//     ///
//     /// @arg[in]    delta is passed in from background draw
//     ///
//     /// @brief      This is the primary drawing function so that all the texture
//     ///             draws can be done in one place in this class. We want as
//     ///             little distance as possible between redraws when possible!
//     ///
//     /// @note       Currently the foreground is not drawn in the custom screen
//     ///             manager. This is because the foreground features the general
//     ///             inventory manager that this screen handler is based on and we
//     ///             do not want to see those text pop ups.
//     /////////////////////////////////////////////////////////////////////////////
//     public void DrawLayers(DrawContext context, float delta) {
//         for (Entry<Integer, ArrayList<GenericLayerT>> layerEntry : layers.entrySet()) {
//             var layerList = layerEntry.getValue();

//             for (var layerListIterator = 0; layerListIterator < layerList.size(); layerListIterator++) {
//                 var layer = layerList.get(layerListIterator);
//                 System.out.println("Drawing layer " + layerEntry.getKey() + " for class type " + layer.getClass().toString());
//                 layer.DrawLayer(context, layerEntry.getKey());
//             }
//         }
//     }

//     /////////////////////////////////////////////////////////////////////////////
//     /// @fn         InBounds
//     ///
//     /// @arg[in]    initX is initial position of X axis
//     ///
//     /// @arg[in]    initY is initial position of Y axis
//     ///
//     /// @arg[in]    endX is the end position of X axis
//     ///
//     /// @arg[in]    endY is the end position of Y axis
//     ///
//     /// @arg[in]    x is the current X value we are comparing in the X axis
//     ///
//     /// @arg[in]    y is the current Y value we are comparing in the Y axis
//     ///
//     /// @brief      Checks if an x,y coordinate position falls within the bounds
//     ///             of a bounded box
//     /////////////////////////////////////////////////////////////////////////////
//     private boolean InBounds(int initX, int initY, int endX, int endY, int x, int y) {
//         return (x >= initX && x <= endX) && (y >= initY && y <= endY);
//     }

//     /////////////////////////////////////////////////////////////////////////////
//     /// @fn         drawBackground
//     ///
//     /// @arg[in]    context is the drawing context of super class
//     ///
//     /// @arg[in]    delta is the change in background draw
//     ///
//     /// @arg[in]    mouseX is the mouse x-axis position
//     ///
//     /// @arg[in]    mouseY is the mouse y-axis position
//     ///
//     /// @brief      This function is an abstract parent class and must be
//     ///             implemented. This is "hijacked" and just being used as our
//     ///             main drawing method of all the background images. There isn't
//     ///             a huge difference of drawing our stuff in background vs the
//     ///             foreground - except possibly foreground is drawn first.
//     /////////////////////////////////////////////////////////////////////////////
//     @Override
//     protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) {
//         DrawLayers(context, delta);
//     }
// }
