package electrosphere.controls;

import electrosphere.entity.CameraEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.AttackTree;
import electrosphere.entity.state.movement.GroundMovementTree;
import electrosphere.entity.state.movement.GroundMovementTree.MovementTreeState;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.main.Globals;
import electrosphere.menu.MenuTransition;
import electrosphere.menu.MenuUtils;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.renderer.ui.Widget;
import electrosphere.util.Utilities;
import java.util.HashMap;
import java.util.List;
import org.joml.Vector2f;
import org.joml.Vector3d;
import org.joml.Vector3f;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.glfw.GLFW.glfwGetCursorPos;
import static org.lwjgl.glfw.GLFW.glfwGetKey;
import static org.lwjgl.glfw.GLFW.glfwGetMouseButton;
import static org.lwjgl.glfw.GLFW.glfwSetInputMode;

/**
 *
 * @author amaterasu
 */
public class ControlHandler {
    
    public static final String DATA_STRING_INPUT_CODE_MOVEMENT_FORWARD = "moveForward";
    public static final String DATA_STRING_INPUT_CODE_MOVEMENT_BACKWARD = "moveBackward";
    public static final String DATA_STRING_INPUT_CODE_MOVEMENT_LEFT = "moveLeft";
    public static final String DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT = "moveRight";
    public static final String DATA_STRING_INPUT_CODE_MOVEMENT_JUMP = "jump";
    public static final String DATA_STRING_INPUT_CODE_MOVEMENT_FALL = "fall";
    public static final String DATA_STRING_INPUT_CODE_ATTACK_PRIMARY = "attackPrimary";
    public static final String DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM = "debugSpawnItem";
    public static final String DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU = "inGameMainMenu";
    
    public static final String DATA_STRING_INPUT_CODE_MENU_INCREMENT = "menuIncrement";
    public static final String DATA_STRING_INPUT_CODE_MENU_DECREMENT = "menuDecrement";
    public static final String DATA_STRING_INPUT_CODE_MENU_SELECT = "menuSelect";
    public static final String DATA_STRING_INPUT_CODE_MENU_BACKOUT = "menuBackout";
    
    
    
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_BACKSPACE = "menuTypeBackspace";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_0 = "menuType0";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_1 = "menuType1";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_2 = "menuType2";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_3 = "menuType3";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_4 = "menuType4";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_5 = "menuType5";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_6 = "menuType6";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_7 = "menuType7";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_8 = "menuType8";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_9 = "menuType9";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_PERIOD = "menuType.";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_A = "menuTypeA";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_B = "menuTypeB";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_C = "menuTypeC";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_D = "menuTypeD";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_E = "menuTypeE";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_F = "menuTypeF";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_G = "menuTypeG";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_H = "menuTypeH";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_I = "menuTypeI";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_J = "menuTypeJ";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_K = "menuTypeK";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_L = "menuTypeL";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_M = "menuTypeM";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_N = "menuTypeN";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_O = "menuTypeO";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_P = "menuTypeP";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_Q = "menuTypeQ";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_R = "menuTypeR";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_S = "menuTypeS";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_T = "menuTypeT";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_U = "menuTypeU";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_V = "menuTypeV";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_W = "menuTypeW";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_X = "menuTypeX";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_Y = "menuTypeY";
    public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_Z = "menuTypeZ";
    
    
    public static enum ControlsState {
        TITLE_PAGE,
        TITLE_MENU,
        MAIN_GAME,
        IN_GAME_MAIN_MENU,
        NO_INPUT,
    }
    
    ControlsState state = ControlsState.TITLE_MENU;
    
    boolean mouseIsVisible = true;
    
    HashMap<String, Control> controls;
    
    ControlHandler(){
        controls = new HashMap();
    }
    
    public static ControlHandler generateExampleControlsMap(){
        ControlHandler handler = new ControlHandler();
        /*
        Main Game controls
        */
        
        /*
        Map the controls
        */
        handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_FORWARD, new Control(true,false,GLFW_KEY_W));
        handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_BACKWARD, new Control(true,false,GLFW_KEY_S));
        handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT, new Control(true,false,GLFW_KEY_A));
        handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT, new Control(true,false,GLFW_KEY_D));
        handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_JUMP, new Control(true,false,GLFW_KEY_SPACE));
        handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_FALL, new Control(true,false,GLFW_KEY_LEFT_CONTROL));
        handler.addControl(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY, new Control(false,true,GLFW_MOUSE_BUTTON_LEFT));
        handler.addControl(DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU, new Control(true,false,GLFW_KEY_ESCAPE));
                
        /*
        Map the menu navigation controls
        */
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_INCREMENT, new Control(true,false,GLFW_KEY_DOWN));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_DECREMENT, new Control(true,false,GLFW_KEY_UP));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_SELECT, new Control(true,false,GLFW_KEY_ENTER));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_BACKOUT, new Control(true,false,GLFW_KEY_ESCAPE));
        
        /*
        Map the typing controls
        */
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_BACKSPACE, new Control(true,false,GLFW_KEY_BACKSPACE));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_0, new Control(true,false,GLFW_KEY_0));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_1, new Control(true,false,GLFW_KEY_1));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_2, new Control(true,false,GLFW_KEY_2));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_3, new Control(true,false,GLFW_KEY_3));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_4, new Control(true,false,GLFW_KEY_4));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_5, new Control(true,false,GLFW_KEY_5));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_6, new Control(true,false,GLFW_KEY_6));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_7, new Control(true,false,GLFW_KEY_7));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_8, new Control(true,false,GLFW_KEY_8));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_9, new Control(true,false,GLFW_KEY_9));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_PERIOD, new Control(true,false,GLFW_KEY_PERIOD));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_A, new Control(true,false,GLFW_KEY_A));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_B, new Control(true,false,GLFW_KEY_B));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_C, new Control(true,false,GLFW_KEY_C));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_D, new Control(true,false,GLFW_KEY_D));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_E, new Control(true,false,GLFW_KEY_E));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_F, new Control(true,false,GLFW_KEY_F));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_G, new Control(true,false,GLFW_KEY_G));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_H, new Control(true,false,GLFW_KEY_H));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_I, new Control(true,false,GLFW_KEY_I));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_J, new Control(true,false,GLFW_KEY_J));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_K, new Control(true,false,GLFW_KEY_K));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_L, new Control(true,false,GLFW_KEY_L));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_M, new Control(true,false,GLFW_KEY_M));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_N, new Control(true,false,GLFW_KEY_N));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_O, new Control(true,false,GLFW_KEY_O));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_P, new Control(true,false,GLFW_KEY_P));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_Q, new Control(true,false,GLFW_KEY_Q));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_R, new Control(true,false,GLFW_KEY_R));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_S, new Control(true,false,GLFW_KEY_S));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_T, new Control(true,false,GLFW_KEY_T));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_U, new Control(true,false,GLFW_KEY_U));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_V, new Control(true,false,GLFW_KEY_V));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_W, new Control(true,false,GLFW_KEY_W));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_X, new Control(true,false,GLFW_KEY_X));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_Y, new Control(true,false,GLFW_KEY_Y));
        handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_Z, new Control(true,false,GLFW_KEY_Z));
        
        /*
        set state
        */
        handler.setHandlerState(ControlsState.TITLE_MENU);
        
        /*
        Save to file
        */
//        Utilities.saveObjectToBakedJsonFile("/Config/keybinds.json", handler);
        
        /*
        Debug controls
        */
        handler.addControl(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM, new Control(true,false,GLFW_KEY_Q));

        /*
        return
        */
        return handler;
    }
    
    
    
    public void pollControls(){
        switch(state){
            
            
            case MAIN_GAME:
                pollMainGameControls();
                pollInGameDebugControls();
                break;
                
                
                
                
                
                
            case TITLE_MENU:
                    pollMenuNavigationControls();
                    /*
                    Typing..
                    */
                    pollTypingControls();
                break;
                
            case IN_GAME_MAIN_MENU:
                pollMenuNavigationControls();
                break;
                
            case NO_INPUT:
                break;
                
        }
    }
    
    public void pollMainGameControls(){
        if(Globals.playerCharacter != null){
            GroundMovementTree movementTree = CreatureUtils.getEntityMovementTree(Globals.playerCharacter);
            AttackTree attackTree = CreatureUtils.getAttackTree(Globals.playerCharacter);
            Vector3f cameraEyeVector = CameraEntityUtils.getCameraEye(Globals.playerCamera);
            /*
            Move forward
            */
            if(controls.containsKey(DATA_STRING_INPUT_CODE_MOVEMENT_FORWARD)){
                if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_FORWARD).isIsKey() && glfwGetKey(Globals.window, controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_FORWARD).getKeyValue()) == GLFW_PRESS){
                    Vector3f newFacingVector = new Vector3f(-cameraEyeVector.x,0,-cameraEyeVector.z).normalize();
                    CreatureUtils.setMovementVector(Globals.playerCharacter, newFacingVector);
//                    System.out.println("Movement vector: " + newFacingVector);
                    if(movementTree.getState()==MovementTreeState.IDLE || movementTree.getState()==MovementTreeState.SLOWDOWN){
                        movementTree.start();
                    }
                    controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_FORWARD).setState(true);
                    //send to server
//                    Vector3f position = EntityUtils.getEntityPosition(Globals.playerCharacter);
//                    EntityMessage outgoingMessage = EntityMessage.constructMoveMessage(
//                            Globals.playerCharacter.getId(),
//                            System.currentTimeMillis(),
//                            position.x,
//                            position.y,
//                            position.z
//                    );
//                    Globals.clientConnection.queueOutgoingMessage(outgoingMessage);
                } else {
                    if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_FORWARD).isState() == true){
                        movementTree.slowdown();
                    }
                    controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_FORWARD).setState(false);
                }
            }
            /*
            Move backward
            */
            if(controls.containsKey(DATA_STRING_INPUT_CODE_MOVEMENT_BACKWARD)){
                if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_BACKWARD).isIsKey() && glfwGetKey(Globals.window, controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_BACKWARD).getKeyValue()) == GLFW_PRESS){
                    CreatureUtils.setMovementVector(Globals.playerCharacter, new Vector3f(cameraEyeVector.x,0,cameraEyeVector.z).normalize());
                    if(movementTree.getState()==MovementTreeState.IDLE || movementTree.getState()==MovementTreeState.SLOWDOWN){
                        movementTree.start();
                    }
                    controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_BACKWARD).setState(true);
                    //send to server
//                    Vector3f position = EntityUtils.getEntityPosition(Globals.playerCharacter);
//                    EntityMessage outgoingMessage = EntityMessage.constructMoveMessage(
//                            Globals.playerCharacter.getId(),
//                            System.currentTimeMillis(),
//                            position.x,
//                            position.y,
//                            position.z
//                    );
//                    Globals.clientConnection.queueOutgoingMessage(outgoingMessage);
                } else {
                    if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_BACKWARD).isState() == true){
                        movementTree.slowdown();
                    }
                    controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_BACKWARD).setState(false);
                }
            }
            /*
            Move left
            */
            if(controls.containsKey(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT)){
                if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT).isIsKey() && glfwGetKey(Globals.window, controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT).getKeyValue()) == GLFW_PRESS){
                    CreatureUtils.setMovementVector(Globals.playerCharacter, new Vector3f(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY((float)(90 * Math.PI / 180)).normalize());
                    if(movementTree.getState()==MovementTreeState.IDLE || movementTree.getState()==MovementTreeState.SLOWDOWN){
                        movementTree.start();
                    }
                    controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT).setState(true);
                    //send to server
//                    Vector3f position = EntityUtils.getEntityPosition(Globals.playerCharacter);
//                    EntityMessage outgoingMessage = EntityMessage.constructMoveMessage(
//                            Globals.playerCharacter.getId(),
//                            System.currentTimeMillis(),
//                            position.x,
//                            position.y,
//                            position.z
//                    );
//                    Globals.clientConnection.queueOutgoingMessage(outgoingMessage);
                } else {
                    if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT).isState() == true){
                        movementTree.slowdown();
                    }
                    controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT).setState(false);
                }
            }
            /*
            Move right
            */
            if(controls.containsKey(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT)){
                if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT).isIsKey() && glfwGetKey(Globals.window, controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT).getKeyValue()) == GLFW_PRESS){
                    CreatureUtils.setMovementVector(Globals.playerCharacter, new Vector3f(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY((float)(-90 * Math.PI / 180)).normalize());
                    if(movementTree.getState()==MovementTreeState.IDLE || movementTree.getState()==MovementTreeState.SLOWDOWN){
                        movementTree.start();
                    }
                    controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT).setState(true);
                    //send to server
//                    Vector3f position = EntityUtils.getEntityPosition(Globals.playerCharacter);
//                    EntityMessage outgoingMessage = EntityMessage.constructMoveMessage(
//                            Globals.playerCharacter.getId(),
//                            System.currentTimeMillis(),
//                            position.x,
//                            position.y,
//                            position.z
//                    );
//                    Globals.clientConnection.queueOutgoingMessage(outgoingMessage);
                } else {
                    if(controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT).isState() == true){
                        movementTree.slowdown();
                    }
                    controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT).setState(false);
                }
            }
            /*
            Move up
            */
            if(controls.containsKey(DATA_STRING_INPUT_CODE_MOVEMENT_JUMP) && glfwGetKey(Globals.window, controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_JUMP).getKeyValue()) == GLFW_PRESS){
                EntityUtils.getPosition(Globals.playerCharacter).add(new Vector3f(0,0.6f,0).mul(1f));
            }
            /*
            Move down
            */
            if(controls.containsKey(DATA_STRING_INPUT_CODE_MOVEMENT_FALL) && glfwGetKey(Globals.window, controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_FALL).getKeyValue()) == GLFW_PRESS){
                EntityUtils.getPosition(Globals.playerCharacter).add(new Vector3f(0,-0.6f,0).mul(1f));
            }
            
            /*
            Attack
            */
            if(controls.containsKey(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY)){
                if(controls.get(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY).isIsMouse() && glfwGetMouseButton(Globals.window, controls.get(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY).getKeyValue()) == GLFW_PRESS){
                    if(controls.get(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY).isState() == false){
                        if(attackTree != null){
                            attackTree.start(EntityDataStrings.ATTACK_MOVE_TYPE_MELEE_SWING_ONE_HAND);
                        }
                    }
                    controls.get(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY).setState(true);
                } else {
                    if(controls.get(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY).isState() == true){
                    }
                    controls.get(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY).setState(false);
                }
            }
            
            
            /*
            Main menu dialog toggle
            */
            if(controls.containsKey(DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU)){
                if(controls.get(DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU).isIsKey() && glfwGetKey(Globals.window, controls.get(DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU).getKeyValue()) == GLFW_PRESS){
                    controls.get(DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU).setState(true);
                } else {
                    if(controls.get(DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU).isState() == true){
                        //make menu dialog visible
                        //change control scheme to in game main menu scheme
                        System.out.println("Press main menu");
                        Globals.currentMenu = MenuUtils.createInGameMainMenu();
                        MenuUtils.makeMenuDrawable(Globals.currentMenu);
                        Globals.controlHandler.setHandlerState(ControlsState.IN_GAME_MAIN_MENU);
                    }
                    controls.get(DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU).setState(false);
                }
            }
            //DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU
        }
    }
    
    public void pollInGameDebugControls(){
        if(controls.containsKey(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM)){
            if(controls.get(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM).isIsKey() && glfwGetKey(Globals.window, controls.get(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM).getKeyValue()) == GLFW_PRESS){
                controls.get(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM).setState(true);
            } else {
                if(controls.get(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM).isState() == true){
                    Entity bow = ItemUtils.spawnBasicItem("Bow");
                    EntityUtils.getPosition(bow).set(1, 5, 2);
                    CollisionObjUtils.positionCharacter(bow, new Vector3f(1, 5, 2));
                }
                controls.get(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM).setState(false);
            }
        }
    }
    
    public void pollMenuNavigationControls(){
        if(controls.containsKey(DATA_STRING_INPUT_CODE_MENU_INCREMENT)){
            if(controls.get(DATA_STRING_INPUT_CODE_MENU_INCREMENT).isIsKey() && glfwGetKey(Globals.window, controls.get(DATA_STRING_INPUT_CODE_MENU_INCREMENT).getKeyValue()) == GLFW_PRESS){
                controls.get(DATA_STRING_INPUT_CODE_MENU_INCREMENT).setState(true);
            } else {
                if(controls.get(DATA_STRING_INPUT_CODE_MENU_INCREMENT).isState() == true){
                    Globals.currentMenu.incrementMenuOption();
                }
                controls.get(DATA_STRING_INPUT_CODE_MENU_INCREMENT).setState(false);
            }
        }
        if(controls.containsKey(DATA_STRING_INPUT_CODE_MENU_DECREMENT)){
            if(controls.get(DATA_STRING_INPUT_CODE_MENU_INCREMENT).isIsKey() && glfwGetKey(Globals.window, controls.get(DATA_STRING_INPUT_CODE_MENU_DECREMENT).getKeyValue()) == GLFW_PRESS){
                controls.get(DATA_STRING_INPUT_CODE_MENU_DECREMENT).setState(true);
            } else {
                if(controls.get(DATA_STRING_INPUT_CODE_MENU_DECREMENT).isState() == true){
                    Globals.currentMenu.decrementMenuOption();
                }
                controls.get(DATA_STRING_INPUT_CODE_MENU_DECREMENT).setState(false);
            }
        }
        if(controls.containsKey(DATA_STRING_INPUT_CODE_MENU_SELECT)){
            if(controls.get(DATA_STRING_INPUT_CODE_MENU_INCREMENT).isIsKey() && glfwGetKey(Globals.window, controls.get(DATA_STRING_INPUT_CODE_MENU_SELECT).getKeyValue()) == GLFW_PRESS){
                controls.get(DATA_STRING_INPUT_CODE_MENU_SELECT).setState(true);
            } else {
                if(controls.get(DATA_STRING_INPUT_CODE_MENU_SELECT).isState() == true){
                    MenuTransition.selectOption(Globals.currentMenu);
                }
                controls.get(DATA_STRING_INPUT_CODE_MENU_SELECT).setState(false);
            }
        }
        if(controls.containsKey(DATA_STRING_INPUT_CODE_MENU_BACKOUT)){
            if(controls.get(DATA_STRING_INPUT_CODE_MENU_INCREMENT).isIsKey() && glfwGetKey(Globals.window, controls.get(DATA_STRING_INPUT_CODE_MENU_BACKOUT).getKeyValue()) == GLFW_PRESS){
                controls.get(DATA_STRING_INPUT_CODE_MENU_BACKOUT).setState(true);
            } else {
                if(controls.get(DATA_STRING_INPUT_CODE_MENU_BACKOUT).isState() == true){
                    MenuTransition.backout(Globals.currentMenu);
                }
                controls.get(DATA_STRING_INPUT_CODE_MENU_BACKOUT).setState(false);
            }
        }
    }
    
    public void pollTypingControls(){
        
        String[] typeKeybinds = {
            DATA_STRING_INPUT_CODE_MENU_TYPE_BACKSPACE,
            DATA_STRING_INPUT_CODE_MENU_TYPE_0,
            DATA_STRING_INPUT_CODE_MENU_TYPE_1,
            DATA_STRING_INPUT_CODE_MENU_TYPE_2,
            DATA_STRING_INPUT_CODE_MENU_TYPE_3,
            DATA_STRING_INPUT_CODE_MENU_TYPE_4,
            DATA_STRING_INPUT_CODE_MENU_TYPE_5,
            DATA_STRING_INPUT_CODE_MENU_TYPE_6,
            DATA_STRING_INPUT_CODE_MENU_TYPE_7,
            DATA_STRING_INPUT_CODE_MENU_TYPE_8,
            DATA_STRING_INPUT_CODE_MENU_TYPE_9,
            DATA_STRING_INPUT_CODE_MENU_TYPE_PERIOD,
        };
        for(String currentKey : typeKeybinds){
            if(controls.get(currentKey).isIsKey() && glfwGetKey(Globals.window, controls.get(currentKey).getKeyValue()) == GLFW_PRESS){
                controls.get(currentKey).setState(true);
            } else {
                if(controls.get(currentKey).isState() == true){
                    MenuTransition.menuHandleKeypress(Globals.currentMenu,currentKey);
                }
                controls.get(currentKey).setState(false);
            }
        }
    }
    
    public Control getControl(String controlName){
        return controls.get(controlName);
    }
    
    public boolean containsControl(String controlName){
        return controls.containsKey(controlName);
    }
    
    public void removeControl(String controlName){
        controls.remove(controlName);
    }
    
    public void addControl(String controlName, Control c){
        controls.put(controlName, c);
    }
    
    public void setHandlerState(ControlsState state){
        this.state = state;
    }
    
    public ControlsState getState(){
        return state;
    }
    
    public void hideMouse(){
        glfwSetInputMode(Globals.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
        mouseIsVisible = false;
    }
    
    public void showMouse(){
        glfwSetInputMode(Globals.window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
        mouseIsVisible = true;
    }
    
    public boolean isMouseVisible(){
        return mouseIsVisible;
    }
    
    public Vector2f getMousePosition(){
        double posX[] = new double[1];
        double posY[] = new double[1];
        glfwGetCursorPos(Globals.window, posX, posY);
        Vector2f rVal = new Vector2f((float)posX[0],(float)posY[0]);
        return rVal;
    }
    
    public static String convertKeycodeToName(int code){
        String rVal = "";
        switch(code){
            case 48:
                rVal = "0";
                break;
            case 49:
                rVal = "1";
                break;
            case 50:
                rVal = "2";
                break;
            case 51:
                rVal = "3";
                break;
            case 52:
                rVal = "4";
                break;
            case 53:
                rVal = "5";
                break;
            case 54:
                rVal = "6";
                break;
            case 55:
                rVal = "7";
                break;
            case 56:
                rVal = "8";
                break;
            case 57:
                rVal = "9";
                break;
            case 65:
                rVal = "A";
                break;
            case 66:
                rVal = "B";
                break;
            case 67:
                rVal = "C";
                break;
            case 68:
                rVal = "D";
                break;
            case 69:
                rVal = "E";
                break;
            case 70:
                rVal = "F";
                break;
            case 71:
                rVal = "G";
                break;
            case 72:
                rVal = "H";
                break;
            case 73:
                rVal = "I";
                break;
            case 74:
                rVal = "J";
                break;
            case 75:
                rVal = "K";
                break;
            case 76:
                rVal = "L";
                break;
            case 77:
                rVal = "M";
                break;
            case 78:
                rVal = "N";
                break;
            case 79:
                rVal = "O";
                break;
            case 80:
                rVal = "P";
                break;
            case 81:
                rVal = "Q";
                break;
            case 82:
                rVal = "R";
                break;
            case 83:
                rVal = "S";
                break;
            case 84:
                rVal = "T";
                break;
            case 85:
                rVal = "U";
                break;
            case 86:
                rVal = "V";
                break;
            case 87:
                rVal = "W";
                break;
            case 88:
                rVal = "X";
                break;
            case 89:
                rVal = "Y";
                break;
            case 90:
                rVal = "Z";
                break;
            case 256:
                rVal = "Escape";
                break;
        }
        return rVal;
    }
    
    
    
}
