package electrosphere.menu.ingame;

import java.util.List;

import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType;
import electrosphere.controls.ControlHandler.ControlsState;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.state.equip.ClientEquipState;
import electrosphere.entity.state.inventory.InventoryUtils;
import electrosphere.entity.state.inventory.RelationalInventoryState;
import electrosphere.entity.state.inventory.UnrelationalInventoryState;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.game.data.creature.type.equip.EquipPoint;
import electrosphere.menu.WindowStrings;
import electrosphere.menu.WindowUtils;
import electrosphere.renderer.ui.elements.Div;
import electrosphere.renderer.ui.elements.ImagePanel;
import electrosphere.renderer.ui.elements.Label;
import electrosphere.renderer.ui.elements.Window;
import electrosphere.renderer.ui.elementtypes.Element;
import electrosphere.renderer.ui.elementtypes.ClickableElement.ClickEventCallback;
import electrosphere.renderer.ui.elementtypes.ContainerElement.YogaAlignment;
import electrosphere.renderer.ui.elementtypes.ContainerElement.YogaJustification;
import electrosphere.renderer.ui.elementtypes.ContainerElement;
import electrosphere.renderer.ui.elementtypes.DraggableElement.DragEventCallback;
import electrosphere.renderer.ui.elementtypes.NavigableElement.NavigationEventCallback;
import electrosphere.renderer.ui.events.ClickEvent;
import electrosphere.renderer.ui.events.DragEvent;
import electrosphere.renderer.ui.events.NavigationEvent;

public class MenuGeneratorsInventory {
    
    public static Window createNaturalInventoryMenu(UnrelationalInventoryState inventory){
        int width = 500;
        int height = 500;

        Window rVal = new Window(Globals.renderingEngine.getOpenGLState(),0,0,width,height,true);
        rVal.setParentAlignItem(YogaAlignment.Center);
        rVal.setParentJustifyContent(YogaJustification.Center);

        //apply yoga so that the screenspace position of the window can be calculated, that allows proper placement of the absolute elements
        rVal.applyYoga(0, 0);

        Div div = Div.createDiv();
        rVal.addChild(div);

        rVal.setOnNavigationCallback(new NavigationEventCallback() {public boolean execute(NavigationEvent event){
            WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowUtils.getInventoryWindowID(inventory.getId())), false);
            Globals.elementManager.unregisterWindow(WindowUtils.getInventoryWindowID(inventory.getId()));
            //
            Globals.openInventoriesCount--;
            if(Globals.openInventoriesCount == 0){
                Globals.controlHandler.hintUpdateControlState(ControlsState.MAIN_GAME);
            }
            //play sound effect
            if(Globals.virtualAudioSourceManager != null){
                Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/closeMenu.ogg", VirtualAudioSourceType.UI, false);
            }
            return false;
        }});

        div.setOnDragRelease(new DragEventCallback() {public boolean execute(DragEvent event){
            if(Globals.draggedItem != null){
                if(Globals.dragSourceInventory != inventory){
                    if(Globals.dragSourceInventory instanceof UnrelationalInventoryState){
                        UnrelationalInventoryState sourceInventory = (UnrelationalInventoryState)Globals.dragSourceInventory;
                        //transfer item
                        // sourceInventory.removeItem(Globals.draggedItem);
                        // inventory.addItem(Globals.draggedItem);
                        // //null out global state
                        // Globals.dragSourceInventory = null;
                        // Globals.draggedItem = null;
                        Entity item = Globals.draggedItem;
                        if(ClientEquipState.hasEquipState(Globals.playerEntity) && InventoryUtils.hasEquipInventory(Globals.playerEntity)){
                            RelationalInventoryState equipInventory = InventoryUtils.getEquipInventory(Globals.playerEntity);
                            ClientEquipState equipState = ClientEquipState.getEquipState(Globals.playerEntity);
                            equipState.commandAttemptUnequip(equipInventory.getItemSlot(item));
                        }
                        //clear item container ui
                        WindowUtils.cleanItemDraggingWindow();
                        //rerender both inventories
                        //re-render inventory
                        WindowUtils.replaceWindow(WindowUtils.getInventoryWindowID(inventory.getId()), MenuGeneratorsInventory.createNaturalInventoryMenu(inventory));
                        //re-render inventory
                        WindowUtils.replaceWindow(WindowUtils.getInventoryWindowID(sourceInventory.getId()), MenuGeneratorsInventory.createNaturalInventoryMenu(sourceInventory));
                    }
                } else {
                    //clear ui
                    WindowUtils.cleanItemDraggingWindow();
                    //re-render inventory
                    WindowUtils.replaceWindow(WindowUtils.getInventoryWindowID(inventory.getId()), MenuGeneratorsInventory.createNaturalInventoryMenu(inventory));
                }
                return false;
            }
            return true;
        }});

        div.setOnClick(new ClickEventCallback() {public boolean execute(ClickEvent event){
            WindowUtils.focusWindow(WindowStrings.WINDOW_MENU_INVENTORY);
            return false;
        }});
        

        //label 1 (inventory)
        div.addChild(Label.createLabel("INVENTORY"));

        int columns = 8;
        int columnWidth = 60;
        int rowHeight = 60;
        for(int i = 0; i < inventory.getCapacity(); i++){
            String texturePath = "Textures/icons/itemIconEmpty.png";
            boolean hasItem = false;
            if(i < inventory.getItems().size()){
                Entity currentItem = inventory.getItems().get(i);
                //get texture path from item
                texturePath = ItemUtils.getItemIcon(currentItem);
                //flag that this isn't an empty slot
                hasItem = true;
            }
            if(!Globals.assetManager.hasLoadedTexture(texturePath)){
                Globals.assetManager.addTexturePathtoQueue(texturePath);
            }
            int posX = (10 + i % columns * columnWidth);
            int posY = 60 + (i / columns * rowHeight);
            int itemPosX = posX;
            int itemPosY = posY;
            int panelWidth = 50;
            int panelHeight = 50;
            ImagePanel panel = new ImagePanel(posX,posY,panelWidth,panelHeight,texturePath);
            panel.setAbsolutePosition(true);
            if(hasItem == true){
                int itemId = i;
                panel.setOnDragStart(new DragEventCallback() {public boolean execute(DragEvent event){
                    // System.out.println("Drag start");
                    Globals.dragSourceInventory = inventory;
                    Globals.draggedItem = inventory.getItems().get(itemId);
                    ContainerElement container = (ContainerElement)panel.getParent();
                    container.removeChild(panel);
                    WindowUtils.pushItemIconToItemWindow(panel);
                    //play sound effect
                    if(Globals.virtualAudioSourceManager != null){
                        Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventoryGrabItem.ogg", VirtualAudioSourceType.UI, false);
                    }
                    return false;
                }});
                panel.setOnDrag(new DragEventCallback() {public boolean execute(DragEvent event){
                    // System.out.println("Drag");
                    panel.setPositionX(event.getCurrentX() - panelWidth / 2);
                    panel.setPositionY(event.getCurrentY() - panelHeight / 2);
                    return false;
                }});
                panel.setOnDragRelease(new DragEventCallback(){public boolean execute(DragEvent event){
                    if(panel.getParent() != div){
                        if(panel.getParent() != null){
                            ContainerElement container = (ContainerElement)panel.getParent();
                            container.removeChild(panel);
                        }
                        div.addChild(panel);
                        Globals.elementManager.fireEvent(event, panel.getAbsoluteX(), panel.getAbsoluteY());
                    }
                    panel.setPositionX(div.getAbsoluteX() + itemPosX);
                    panel.setPositionY(div.getAbsoluteY() + itemPosY);
                    return false;
                }});
            } else {
                panel.setOnDragRelease(new DragEventCallback(){public boolean execute(DragEvent event){
                    if(Globals.dragSourceInventory instanceof RelationalInventoryState){
                        RelationalInventoryState sourceInventory = (RelationalInventoryState) Globals.dragSourceInventory;
                        Entity item = Globals.draggedItem;
                        if(ClientEquipState.hasEquipState(Globals.playerEntity) && InventoryUtils.hasEquipInventory(Globals.playerEntity)){
                            RelationalInventoryState equipInventory = InventoryUtils.getEquipInventory(Globals.playerEntity);
                            ClientEquipState equipState = ClientEquipState.getEquipState(Globals.playerEntity);
                            equipState.commandAttemptUnequip(equipInventory.getItemSlot(item));
                        }
                        //update ui
                        // Globals.dragSourceInventory = null;
                        // Globals.draggedItem = null;
                        //clear item container ui
                        WindowUtils.cleanItemDraggingWindow();
                        //rerender both inventories
                        //re-render inventory
                        WindowUtils.replaceWindow(WindowStrings.WINDOW_CHARACTER, MenuGeneratorsInventory.createCharacterInventoryMenu(sourceInventory));
                        //re-render inventory
                        WindowUtils.replaceWindow(WindowUtils.getInventoryWindowID(inventory.getId()), MenuGeneratorsInventory.createNaturalInventoryMenu(inventory));
                        //play sound effect
                        if(Globals.virtualAudioSourceManager != null){
                            Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventorySlotItem.ogg", VirtualAudioSourceType.UI, false);
                        }
                    }
                    //now the fun begins :)
                    //if transfer item
                    //  remove item from current inventory
                    //  place item in new inventory
                    //  trigger recreation of the menu
                    //if drop item
                    //  remove item from current inventory
                    //  create item in world in front of character
                    //  trigger recreation of the menu
                    //if neither of above
                    //  replace item icon position to origin
                    // System.out.println("Release drag");
                    return false;
                }});
            }
            // imagePanel.setWidth(width);
            // imagePanel.setHeight(height);
            // imagePanel.setTexture(Globals.assetManager.fetchTexture(Globals.blackTexture));
            div.addChild(panel);
        }

        return rVal;
    }


    public static Window createCharacterInventoryMenu(RelationalInventoryState inventory){
        // int screenTop = Globals.WINDOW_HEIGHT - 150;
        int width = 500;
        int height = 500;
        // int screenLeft = (Globals.WINDOW_WIDTH - width)/2;
        Window rVal = new Window(Globals.renderingEngine.getOpenGLState(),0,0,width,height,true);

        Div div = Div.createDiv();
        rVal.addChild(div);

        rVal.setOnNavigationCallback(new NavigationEventCallback() {public boolean execute(NavigationEvent event){
            WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_CHARACTER), false);
            Globals.elementManager.unregisterWindow(WindowStrings.WINDOW_CHARACTER);
            //
            Globals.openInventoriesCount--;
            if(Globals.openInventoriesCount == 0){
                Globals.controlHandler.hintUpdateControlState(ControlsState.MAIN_GAME);
            }
            //play sound effect
            if(Globals.virtualAudioSourceManager != null){
                Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/closeMenu.ogg", VirtualAudioSourceType.UI, false);
            }
            return false;
        }});

        div.setOnDragRelease(new DragEventCallback() {public boolean execute(DragEvent event){
            if(Globals.draggedItem != null){
                if(Globals.dragSourceInventory instanceof UnrelationalInventoryState){
                    UnrelationalInventoryState sourceInventory = (UnrelationalInventoryState)Globals.dragSourceInventory;
                    //null out global state
                    Globals.dragSourceInventory = null;
                    Globals.draggedItem = null;
                    //clear item container ui
                    WindowUtils.cleanItemDraggingWindow();
                    //rerender both inventories
                    //re-render inventory
                    WindowUtils.replaceWindow(WindowStrings.WINDOW_CHARACTER, MenuGeneratorsInventory.createCharacterInventoryMenu(inventory));
                    //re-render inventory
                    WindowUtils.replaceWindow(WindowUtils.getInventoryWindowID(sourceInventory.getId()), MenuGeneratorsInventory.createNaturalInventoryMenu(sourceInventory));
                }
                return false;
            }
            return true;
        }});

        div.setOnClick(new ClickEventCallback() {public boolean execute(ClickEvent event){
            WindowUtils.focusWindow(WindowStrings.WINDOW_CHARACTER);
            return false;
        }});
        

        //label 1 (inventory)
        Label inventoryLabel = new Label(1.0f);
        inventoryLabel.setText("CHARACTER");
        div.addChild(inventoryLabel);

        // int columns = 8;
        // int columnWidth = 60;
        // int rowHeight = 60;
        int slotSpacing = 30;

        List<String> slots = inventory.getSlots();
        int numSlots = slots.size();
        EquipPoint equipPoint = null;
        // int numRows = (numSlots / 2) + (numSlots % 2 == 1 ? 1 : 0);

        int incrementer = 0;
        for(int i = 0; i < numSlots; i++){
            String texturePath = "Textures/icons/itemIconEmpty.png";
            boolean hasItem = false;
            String slotId = slots.get(i);
            equipPoint = inventory.getEquipPointFromSlot(slotId);
            if(!equipPoint.isCombinedPoint()){
                if(inventory.getItemSlot(slotId) != null){
                    Entity currentItem = inventory.getItemSlot(slotId);
                    //get texture path from item
                    texturePath = ItemUtils.getItemIcon(currentItem);
                    //flag that this isn't an empty slot
                    hasItem = true;
                } else if(inventory.getCombinedPoint(slotId) != null && inventory.hasItemInSlot(inventory.getCombinedPoint(slotId).getEquipPointId())){
                    Entity currentItem = inventory.getItemSlot(inventory.getCombinedPoint(slotId).getEquipPointId());
                    //get texture path from item
                    texturePath = ItemUtils.getItemIcon(currentItem);
                    //flag that this isn't an empty slot
                    hasItem = true;
                    equipPoint = inventory.getCombinedPoint(slotId);
                    slotId = equipPoint.getEquipPointId();
                }
                if(!Globals.assetManager.hasLoadedTexture(texturePath)){
                    Globals.assetManager.addTexturePathtoQueue(texturePath);
                }
                int panelWidth = 50;
                int panelHeight = 50;
                int posX = 20;
                if((incrementer % 2) == 1){
                    posX = posX + 400;
                }
                int posY = 60 + (i / 2 * (panelHeight + slotSpacing));
                int itemPosX = posX;
                int itemPosY = posY;
                ImagePanel panel = new ImagePanel(posX,posY,panelWidth,panelHeight,texturePath);
                panel.setAbsolutePosition(true);
                if(hasItem == true){
                    //literally just here to get around finality of variable within callback
                    String finalSlotId = slotId;
                    panel.setOnDragStart(new DragEventCallback() {
                        public boolean execute(DragEvent event){
                        // System.out.println("Drag start");
                        Globals.dragSourceInventory = inventory;
                        Globals.draggedItem = inventory.getItemSlot(finalSlotId);
                        ContainerElement container = (ContainerElement)panel.getParent();
                        container.removeChild(panel);
                        WindowUtils.pushItemIconToItemWindow(panel);
                        //play sound effect
                        if(Globals.virtualAudioSourceManager != null){
                            Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventoryGrabItem.ogg", VirtualAudioSourceType.UI, false);
                        }
                        return false;
                    }});
                    panel.setOnDrag(new DragEventCallback() {public boolean execute(DragEvent event){
                        // System.out.println("Drag");
                        panel.setPositionX(event.getCurrentX() - panelWidth / 2);
                        panel.setPositionY(event.getCurrentY() - panelHeight / 2);
                        return false;
                    }});
                    panel.setOnDragRelease(new DragEventCallback(){public boolean execute(DragEvent event){
                        if(panel.getParent() != div){
                            if(panel.getParent() != null){
                                ContainerElement container = (ContainerElement)panel.getParent();
                                container.removeChild(panel);
                            }
                            div.addChild(panel);
                            Globals.elementManager.fireEvent(event, panel.getAbsoluteX(), panel.getAbsoluteY());
                        }
                        panel.setPositionX(div.getAbsoluteX() + itemPosX);
                        panel.setPositionY(div.getAbsoluteY() + itemPosY);
                        return false;
                    }});
                    
                } else {
                    int itemId = i;
                    panel.setOnDragRelease(new DragEventCallback(){public boolean execute(DragEvent event){
                        // panel.setPositionX(posX);
                        // panel.setPositionY(posY);
                        if(Globals.dragSourceInventory instanceof UnrelationalInventoryState){
                            UnrelationalInventoryState sourceInventory = (UnrelationalInventoryState) Globals.dragSourceInventory;
                            Entity item = Globals.draggedItem;
                            if(inventory.canEquipItemToSlot(item, slots.get(itemId))){
                                //fire equip event to equip state
                                ClientEquipState equipState = ClientEquipState.getEquipState(Globals.playerEntity);
                                equipState.commandAttemptEquip(item,inventory.getEquipPointFromSlot(slots.get(itemId)));
                                //play sound effect
                                if(Globals.virtualAudioSourceManager != null){
                                    Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventorySlotItem.ogg", VirtualAudioSourceType.UI, false);
                                }
                            } else if(inventory.canEquipItemToCombinedSlot(item, slots.get(itemId))){
                                EquipPoint combinedPoint = inventory.getCombinedPoint(slots.get(itemId));
                                //fire equip event to equip state
                                ClientEquipState equipState = ClientEquipState.getEquipState(Globals.playerEntity);
                                equipState.commandAttemptEquip(item,combinedPoint);
                                //play sound effect
                                if(Globals.virtualAudioSourceManager != null){
                                    Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventorySlotItem.ogg", VirtualAudioSourceType.UI, false);
                                }
                            }
                            //update ui
                            Globals.dragSourceInventory = null;
                            Globals.draggedItem = null;
                            //clear item container ui
                            WindowUtils.cleanItemDraggingWindow();
                            //rerender both inventories
                            //re-render inventory
                            WindowUtils.replaceWindow(WindowStrings.WINDOW_CHARACTER, MenuGeneratorsInventory.createCharacterInventoryMenu(inventory));
                            //re-render inventory
                            WindowUtils.replaceWindow(WindowUtils.getInventoryWindowID(sourceInventory.getId()), MenuGeneratorsInventory.createNaturalInventoryMenu(sourceInventory));
                        }
                        //now the fun begins :)
                        //if transfer item
                        //  remove item from current inventory
                        //  place item in new inventory
                        //  trigger recreation of the menu
                        //if drop item
                        //  remove item from current inventory
                        //  create item in world in front of character
                        //  trigger recreation of the menu
                        //if neither of above
                        //  replace item icon position to origin
                        // System.out.println("Release drag");
                        //rebuild inventory windows
                        return false;
                    }});
                }
                div.addChild(panel);

                //create the slot text
                posX = 80;
                if((incrementer % 2) == 1){
                    posX = posX + 190;
                }
                posY = posY + 15;
                Label slotText = new Label(0.7f);
                slotText.setText(slots.get(i));
                slotText.setPositionX(posX);
                slotText.setPositionY(posY);
                slotText.setAbsolutePosition(true);
                div.addChild(slotText);

                incrementer++;
            }
        }

        return rVal;
    }

    public static Element worldItemDropCaptureWindow(){
        Window rVal = new Window(Globals.renderingEngine.getOpenGLState(),0,0,Globals.WINDOW_WIDTH,Globals.WINDOW_HEIGHT,true);
        Div div = Div.createDiv();
        div.setOnDragRelease(new DragEventCallback() {public boolean execute(DragEvent event){
            if(Globals.draggedItem != null){
                if(Globals.dragSourceInventory instanceof UnrelationalInventoryState){
                    UnrelationalInventoryState inventory = (UnrelationalInventoryState) Globals.dragSourceInventory;
                    //drop item
                    InventoryUtils.clientAttemptEjectItem(Globals.playerEntity,Globals.draggedItem);
                    //clear ui
                    WindowUtils.cleanItemDraggingWindow();
                    String sourceWindowId = WindowUtils.getInventoryWindowID(inventory.getId());
                    WindowUtils.replaceWindow(sourceWindowId,MenuGeneratorsInventory.createNaturalInventoryMenu(inventory));
                    //null globals
                    Globals.dragSourceInventory = null;
                    Globals.draggedItem = null;
                    return false;
                } else if(Globals.dragSourceInventory instanceof RelationalInventoryState){
                    RelationalInventoryState inventory = (RelationalInventoryState) Globals.dragSourceInventory;
                    //drop item
                    InventoryUtils.clientAttemptEjectItem(Globals.playerEntity,Globals.draggedItem);
                    //clear ui
                    WindowUtils.cleanItemDraggingWindow();
                    String sourceWindowId = WindowStrings.WINDOW_CHARACTER;
                    WindowUtils.replaceWindow(sourceWindowId,MenuGeneratorsInventory.createCharacterInventoryMenu(inventory));
                    //null globals
                    Globals.dragSourceInventory = null;
                    Globals.draggedItem = null;
                    return false;
                }
            }
            return true;
        }});
        div.setPositionX(0);
        div.setPositionY(0);
        div.setWidth(Globals.WINDOW_WIDTH);
        div.setHeight(Globals.WINDOW_HEIGHT);
        rVal.addChild(div);
        return rVal;
    }

}
