package client.gui.container;

import java.util.List;
import java.util.Set;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;

import client.gui.Font;
import client.gui.Gui;
import client.gui.element.InventoryButton;
import client.renderer.Drawing;
import client.renderer.GlState;
import client.renderer.ItemRenderer;
import client.renderer.entity.RenderItem;
import client.window.Button;
import common.collect.Lists;
import common.collect.Sets;
import common.color.TextColor;
import common.inventory.Container;
import common.inventory.InventoryPlayer;
import common.inventory.Slot;
import common.item.CheatTab;
import common.item.ItemStack;
import common.packet.CPacketCheat;
import common.util.ExtMath;

public abstract class GuiContainer extends Gui
{
	private class Overlay {
		private final ItemStack stack;
		private final int x;
		private final int y;
		private final String alt;
		
		private Overlay(ItemStack stack, int x, int y, String alt) {
			this.stack = stack;
			this.x = x;
			this.y = y;
			this.alt = alt;
		}
	}

    private static final List<ItemStack> ITEM_LIST = Lists.<ItemStack>newArrayList();
    
    private static CheatTab selectedTab = CheatTab.BLOCKS;
//    /** The location of the inventory background texture */
//    protected static final String inventoryBackground = "textures/gui/inventory.png";

	protected RenderItem itemRender;
//	public int width;
//	public int height;

    /** The X size of the inventory window in pixels. */
    protected int xSize = 176;

    /** The Y size of the inventory window in pixels. */
    protected int ySize = 166;

    /** A list of the players inventory slots */
    public Container inventorySlots;

//    /**
//     * Starting X position for the Gui. Inconsistent use for Gui backgrounds.
//     */
//    protected int guiLeft;
//
//    /**
//     * Starting Y position for the Gui. Inconsistent use for Gui backgrounds.
//     */
//    protected int guiTop;

    /** holds the slot currently hovered */
    private Slot theSlot;

    /** Used when touchscreen is enabled. */
    private Slot clickedSlot;

    /** Used when touchscreen is enabled. */
    private boolean isRightMouseClick;

    /** Used when touchscreen is enabled */
    private ItemStack draggedStack;
    private int touchUpX;
    private int touchUpY;
    private Slot returningStackDestSlot;
    private long returningStackTime;

    /** Used when touchscreen is enabled */
    private ItemStack returningStack;
    private Slot currentDragTargetSlot;
    private long dragItemDropDelay;
    protected final Set<Slot> dragSplittingSlots = Sets.<Slot>newHashSet();
    protected final List<Overlay> drawnOverlays = Lists.<Overlay>newArrayList();
    protected boolean dragSplitting;
    private int dragSplittingLimit;
    private int dragSplittingButton;
    private boolean ignoreMouseUp;
    private int dragSplittingRemnant;
    private long lastClickTime;
    private Slot lastClickSlot;
    private int lastClickButton;
    private boolean doubleClick;
    private ItemStack shiftClickedSlot;

    protected int container_x;
    protected int container_y;
    protected int container_w;
    protected int container_h;

    private int hover_x;
    private int hover_y;
    private String tooltip;

    private float currentScroll;
    private boolean isScrolling;
    private boolean wasClicking;
    private ItemStack cheatStack;

	public void drawString(String text, int x, int y) {
		x = x * 2 + this.container_x;
		y = y * 2 + this.container_y;
		Drawing.drawText(text, x, y, 0xffffffff);
	}
	
	public int getStringWidth(String text) {
		return Drawing.getSize(text).xpos / 2;
	}
	
    public void rect(int x, int y, int width, int height, int color) {
    	Drawing.drawRect(this.container_x + x * 2, this.container_y + y * 2, width * 2, height * 2, 0xff000000 | color);
	}
    
	public InventoryButton button(int x, int y, int w, int h) {
		return this.add(new InventoryButton(this.container_x + x * 2, this.container_y + y * 2, w * 2, h * 2));
	}
	
//	public void uidims(int w, int h) {
//	}

	public void mouse(Button btn, int x, int y, boolean ctrl, boolean shift) {
		super.mouse(btn, x, y, ctrl, shift);
//    public void click(Button btn, int x, int y) {
//		if(this.openGui != null) {
//			int x = SKC.getMouseX() * this.openGui.width / this.gm.fb_x;
//			int y = this.openGui.height - SKC.getMouseY() * this.openGui.height / this.gm.fb_y - 1;
		this.mouseClicked((x - this.container_x) / 2, (y - this.container_y) / 2, btn.ordinal()); //TODO: enum
//		}
	}
    
    public void mouserel(Button btn, int x, int y) {
    	super.mouserel(btn, x, y);
//		if(this.openGui != null) {
//			int x = SKC.getMouseX() * this.openGui.width / this.gm.fb_x;
//			int y = this.openGui.height - SKC.getMouseY() * this.openGui.height / this.gm.fb_y - 1;
		this.mouseReleased((x - this.container_x) / 2, (y - this.container_y) / 2, btn.ordinal()); //TODO: enum
//		}
	}
	
	public void drag(int x, int y) {
		super.drag(x, y);
//		if(this.openGui != null) {
//			int x = SKC.getMouseX() * this.openGui.width / this.gm.fb_x;
//			int y = this.openGui.height - SKC.getMouseY() * this.openGui.height / this.gm.fb_y - 1;
		if(Button.MOUSE_LEFT.isDown() || Button.MOUSE_RIGHT.isDown() || Button.MOUSE_MIDDLE.isDown())
			this.mouseDragged((x - this.container_x) / 2, (y - this.container_y) / 2);
//		}
	}

    public GuiContainer(Container inventorySlotsIn)
    {
        this.inventorySlots = inventorySlotsIn;
        this.ignoreMouseUp = true;
    }
	
	public void init(int width, int height) {
		this.itemRender = this.gm.getRenderItem();
		this.tooltip = null;
		this.cheatStack = null;
//		this.width = width;
//		this.height = height;
//		this.initialize(this.gm.getGame());
//		this.container_x = this.container_y = this.container_w = this.container_h = 0;
		this.container_x = (width - (this.container_w = (this.xSize * 2))) / 2;
		this.container_y = (height - (this.container_h = (this.ySize * 2))) / 2;
		this.initGui();
		this.addButtons();
	}

	public void hover(String text, int x, int y) {
		this.tooltip = text;
		this.hover_x = x * 2 + this.container_x + 16;
		this.hover_y = y * 2 + this.container_y + 16;
	}
	
	public String getTitle() {
		return "Inventar";
	}
    
//    public int getXSize() {
//    	return this.xSize;
//    }
//    
//    public int getYSize() {
//    	return this.ySize;
//    }

//	public final void initialize(Game gm) {
//	}

    /**
     * Adds the buttons (and other controls) to the screen in question. Called when the GUI is displayed and when the
     * window resizes, the buttonList is cleared beforehand.
     */
    public void initGui()
    {
        this.gm.player.openContainer = this.inventorySlots;
//        this.guiLeft = (this.width - this.xSize) / 2;
//        this.guiTop = (this.height - this.ySize) / 2;
//        this.addButtons();
        if(this.gm.itemCheat) {
//            CheatTab i = selectedTab;
//            selectedTab = null;
            this.setCurrentTab(selectedTab);
        }
    }
    
    public void addButtons() {
//		this.uidims(this.xSize, this.ySize);
    	if(this.inventorySlots != null) {
	        for (int i1 = 0; i1 < this.inventorySlots.inventorySlots.size(); ++i1) {
	        	Slot slot = (Slot)this.inventorySlots.inventorySlots.get(i1);
	        	this.button(slot.xDisplayPosition - 1, slot.yDisplayPosition - 1, 18, 18);
	        }
    	}
    	if(this.gm.itemCheat) {
	    	for (int k = 0; k < 9; ++k)
	        {
	            for (int l = 0; l < 12; ++l) {
	            	this.button(this.xSize + 2 + 18 * l, k * 18, 18, 18);
	            }
	        }
	    	for(CheatTab tab : CheatTab.values()) {
	        	this.button(this.xSize + 2 + 18 * tab.getHorizontal(), 9 * 18 + 4 + 20 * tab.getVertical(), 18, 18);
	        }
    	}
    }
    
    protected void drawSlots(int mouseX, int mouseY) {
        for (int i1 = 0; i1 < this.inventorySlots.inventorySlots.size(); ++i1)
        {
            Slot slot = (Slot)this.inventorySlots.inventorySlots.get(i1);
            this.drawSlot(slot);

            if (this.isMouseOverSlot(slot, mouseX, mouseY) && slot.canBeHovered())
            {
                this.theSlot = slot;
            }
        }
    	
    	if(this.gm.itemCheat) {
	        int i = (ITEM_LIST.size() + 12 - 1) / 12 - 9;
	        int j = (int)((double)(this.currentScroll * (float)i) + 0.5D);
	
	        if (j < 0)
	        {
	            j = 0;
	        }
	
	        for (int k = 0; k < 9; ++k)
	        {
	            for (int l = 0; l < 12; ++l)
	            {
	                int i1 = l + (k + j) * 12;
	
	                if (i1 >= 0 && i1 < ITEM_LIST.size()) {
	
	                    this.itemRender.zLevel = 100.0F;
	                    GlState.enableDepth();
	                    this.itemRender.renderItemAndEffectIntoGUI(ITEM_LIST.get(i1), this.xSize + 2 + 18 * l + 1, k * 18 + 1);
	                    this.itemRender.zLevel = 0.0F;
	                    if(this.isPointInRegion(this.xSize + 2 + 18 * l + 1, k * 18 + 1, 16, 16, mouseX, mouseY))
	                        this.renderToolTip(ITEM_LIST.get(i1), mouseX, mouseY);
	                }
	            }
	        }
	
	        for (CheatTab tabs : CheatTab.values())
	        {
	            this.drawTab(tabs);
	        }
    	}
    }

    public void drawOverlays() {
    	for(Overlay overlay : this.drawnOverlays) {
    		this.renderItemOverlayIntoGUI(overlay.stack, overlay.x, overlay.y, overlay.alt);
    	}
    	this.drawnOverlays.clear();
		if(this.tooltip != null) {
			int width = Drawing.getBoxWidth(this.tooltip);
			Drawing.drawTextbox(this.tooltip, this.hover_x + width > this.gm.fb_x ? this.hover_x - width - 32 : this.hover_x, this.hover_y, 0xaf000000);
		}
		this.tooltip = null;
    }

    /**
     * Draws the screen and all the components in it. Args : mouseX, mouseY, renderPartialTicks
     */
    public void drawScreen(int mouseX, int mouseY)
    {
    	if(this.gm == null)
    		return;
    	if(this.gm.itemCheat) {
	        boolean flag = Button.MOUSE_LEFT.isDown(); //TODO: remove?
	        int x1 = this.xSize + 2 + 12 * 18 + 1;
	        int y1 = 1;
	        int x2 = x1 + 10;
	        int y2 = y1 + 112 + 18 * 4;
	
	        if (!this.wasClicking && flag && mouseX >= x1 && mouseY >= y1 && mouseX < x2 && mouseY < y2)
	        {
	            this.isScrolling = this.needsScrollBars();
	        }
	
	        if (!flag)
	        {
	            this.isScrolling = false;
	        }
	
	        this.wasClicking = flag;
	
	        if (this.isScrolling)
	        {
	            this.currentScroll = ((float)(mouseY - y1) - 7.5F) / ((float)(y2 - y1) - 15.0F);
	            this.currentScroll = ExtMath.clampf(this.currentScroll, 0.0F, 1.0F);
	        }
    	}
//        this.drawGradientRect(0, 0, this.width, this.height, -1072689136, -804253680);
//        int i = this.guiLeft;
//        int j = this.guiTop;
//        this.drawGuiContainerBackgroundLayer(mouseX, mouseY);
        GlState.disableRescaleNormal();
        ItemRenderer.disableStandardItemLighting();
        GlState.disableLighting();
        GlState.disableDepth();
//        super.drawScreen(mouseX, mouseY, partialTicks);
        ItemRenderer.enableGUIStandardItemLighting();
//        SKC.glPushMatrix();
//        SKC.glTranslatef((float)i, (float)j, 0.0F);
        GlState.color(1.0F, 1.0F, 1.0F, 1.0F);
        GlState.enableRescaleNormal();
        this.theSlot = null;
        int k = 240;
        int l = 240;
        GL13.glMultiTexCoord2f(GL13.GL_TEXTURE1, (float)k / 1.0F, (float)l / 1.0F);
        GlState.color(1.0F, 1.0F, 1.0F, 1.0F);
        
        this.drawSlots(mouseX, mouseY);

        ItemRenderer.disableStandardItemLighting();
//        this.drawGuiContainerForegroundLayer(mouseX, mouseY);
        ItemRenderer.enableGUIStandardItemLighting();
        InventoryPlayer inventoryplayer = this.gm.player.inventory;
        ItemStack itemstack = this.draggedStack == null ? inventoryplayer.getItemStack() : this.draggedStack;
        if(this.gm.itemCheat)
        	itemstack = itemstack == null ? this.cheatStack : itemstack;

        if (itemstack != null)
        {
            int j2 = 8;
            int k2 = this.draggedStack == null ? 8 : 16;
            String s = null;

            if (this.draggedStack != null && this.isRightMouseClick)
            {
                itemstack = itemstack.copy();
                itemstack.size = ExtMath.ceilf((float)itemstack.size / 2.0F);
            }
            else if (this.dragSplitting && this.dragSplittingSlots.size() > 1)
            {
                itemstack = itemstack.copy();
                itemstack.size = this.dragSplittingRemnant;

                if (itemstack.size == 0)
                {
                    s = "" + TextColor.YELLOW + "0";
                }
            }
            else if(itemstack == this.cheatStack) {
            	s = TextColor.DGREEN + "+" + TextColor.GREEN + ItemStack.formatAmount(itemstack.size);
            }

            this.drawItemStack(itemstack, mouseX - j2, mouseY - k2, s);
        }

        if (this.returningStack != null)
        {
            float f = (float)(System.currentTimeMillis() - this.returningStackTime) / 100.0F;

            if (f >= 1.0F)
            {
                f = 1.0F;
                this.returningStack = null;
            }

            int l2 = this.returningStackDestSlot.xDisplayPosition - this.touchUpX;
            int i3 = this.returningStackDestSlot.yDisplayPosition - this.touchUpY;
            int l1 = this.touchUpX + (int)((float)l2 * f);
            int i2 = this.touchUpY + (int)((float)i3 * f);
            this.drawItemStack(this.returningStack, l1, i2, (String)null);
        }

//        SKC.glPopMatrix();

        if (inventoryplayer.getItemStack() == null && this.cheatStack == null && this.theSlot != null && this.theSlot.getHasStack())
        {
            ItemStack itemstack1 = this.theSlot.getStack();
            this.renderToolTip(itemstack1, mouseX, mouseY);
        }

        GlState.enableLighting();
        GlState.enableDepth();
        ItemRenderer.enableStandardItemLighting();

        if(this.gm.itemCheat) {
	        for (CheatTab tab : CheatTab.values())
	        {
	            if (this.renderInventoryHoveringText(tab, mouseX, mouseY))
	            {
	                break;
	            }
	        }
	
	        GlState.color(1.0F, 1.0F, 1.0F, 1.0F);
	        GlState.disableLighting();
        }
    }

    /**
     * Render an ItemStack. Args : stack, x, y, format
     */
    private void drawItemStack(ItemStack stack, int x, int y, String altText)
    {
        GL11.glTranslatef(0.0F, 0.0F, 32.0F);
//        this.zLevel = 200.0F;
        this.itemRender.zLevel = 200.0F;
        this.itemRender.renderItemAndEffectIntoGUI(stack, x, y);
        this.drawnOverlays.add(new Overlay(stack, x, y - (this.draggedStack == null ? 0 : 8), altText));
//        this.zLevel = 0.0F;
        this.itemRender.zLevel = 0.0F;
    }

	protected void renderToolTip(ItemStack stack, int x, int y) {
		List<String> list = stack.getTooltip(this.gm.player);
		StringBuilder sb = new StringBuilder();
		for(int i = 0; i < list.size(); ++i) {
			if(i != 0)
				sb.append("\n" + TextColor.LGRAY + (String)list.get(i));
			else
				sb.append((String)list.get(i));
		}
		this.hover(sb.toString(), x, y);
	}

    /**
     * Draw the foreground layer for the GuiContainer (everything in front of the items). Args : mouseX, mouseY
     */
    public void drawGuiContainerForegroundLayer()
    {
    }
    
    public void drawGuiContainerBackgroundLayer() {
    }
    
    public void draw() {
    	super.draw();
    	if(this.gm.itemCheat) {
            int i = this.xSize + 2 + 12 * 18 + 1;
            int j = 1;
            int k = j + 184;
            this.rect(i, j, 8, 182, this.needsScrollBars() ? 0x303030 : 0x202020);
            this.rect(i, j + (int)((float)(k - j - 17) * this.currentScroll), 8, 15, this.needsScrollBars() ? 0x808080 : 0x606060);
//            CheatTab tab = CheatTab.TABS[selectedTab];
            this.rect(this.xSize + 2 + 18 * selectedTab.getHorizontal(), 9 * 18 + 4 + 20 * selectedTab.getVertical() - 2, 18, 2, 0xffffff);
    	}
		this.drawGuiContainerBackgroundLayer();
    	if(this.gm.itemCheat) {
//	        CheatTab tab = CheatTab.TABS[selectedTab];
	        this.drawString(selectedTab.getName(), this.xSize + 2 + 4, -10);
	        this.drawString("Vorsicht: Schummeln wird mit Keule bestraft", this.xSize + 2 + 4, 18 * (9 + (CheatTab.values().length + 11) / 12) + 10);
	        this.drawString("(Halte Strg beim Klick für vollen Stapel)", this.xSize + 2 + 4, 18 * (9 + (CheatTab.values().length + 11) / 12) + 20);
    	}
		this.drawGuiContainerForegroundLayer();
    }

	public void drawPost() {
    	GL11.glPushMatrix();
    	GL11.glTranslatef((float)((this.gm.fb_x - this.xSize * 2) / 2), (float)((this.gm.fb_y - this.ySize * 2) / 2), 0.0f);
//        int k1 = SKC.getMouseX();
//        int l1 = this.gm.fb_y - SKC.getMouseY() - 1;
    	GL11.glScalef(2.0f, 2.0f, 2.0f);
		this.drawScreen((this.gm.mouse_x - this.container_x) / 2, (this.gm.mouse_y - this.container_y) / 2);
        GL11.glPopMatrix();
        ItemRenderer.disableStandardItemLighting();
//        GlState.color(1.0f, 1.0f, 1.0f, 1.0f);
	}

    private void drawSlot(Slot slotIn)
    {
        int i = slotIn.xDisplayPosition;
        int j = slotIn.yDisplayPosition;
        ItemStack itemstack = slotIn.getStack();
        boolean flag = false;
        boolean flag1 = slotIn == this.clickedSlot && this.draggedStack != null && !this.isRightMouseClick;
        ItemStack itemstack1 = this.gm.player.inventory.getItemStack();
        String s = null;

        if (slotIn == this.clickedSlot && this.draggedStack != null && this.isRightMouseClick && itemstack != null)
        {
            itemstack = itemstack.copy();
            itemstack.size /= 2;
        }
        else if (this.dragSplitting && this.dragSplittingSlots.contains(slotIn) && itemstack1 != null)
        {
            if (this.dragSplittingSlots.size() == 1)
            {
                return;
            }

            if (Container.canAddItemToSlot(slotIn, itemstack1, true) && this.inventorySlots.canDragIntoSlot(slotIn))
            {
                itemstack = itemstack1.copy();
                flag = true;
                Container.computeStackSize(this.dragSplittingSlots, this.dragSplittingLimit, itemstack, slotIn.getStack() == null ? 0 : slotIn.getStack().size);

                if (itemstack.size > itemstack.getMaxStackSize())
                {
                    s = TextColor.YELLOW + ItemStack.formatAmount(itemstack.getMaxStackSize());
                    itemstack.size = itemstack.getMaxStackSize();
                }

                if (itemstack.size > slotIn.getItemStackLimit(itemstack))
                {
                    s = TextColor.YELLOW + ItemStack.formatAmount(slotIn.getItemStackLimit(itemstack));
                    itemstack.size = slotIn.getItemStackLimit(itemstack);
                }
            }
            else
            {
                this.dragSplittingSlots.remove(slotIn);
                this.updateDragSplitting();
            }
        }

//        this.zLevel = 100.0F;
        this.itemRender.zLevel = 100.0F;

//        if (itemstack == null)
//        {
//            String s1 = slotIn.getSlotTexture();
//
//            if (s1 != null)
//            {
//                TextureAtlasSprite sprite = this.gm.getTextureMapBlocks().getAtlasSprite(s1);
//                GlState.disableLighting();
//                this.gm.getTextureManager().bindTexture(TextureMap.locationBlocksTexture);
//                this.rectuv(i, j, 16, 16, sprite.getMinU(), sprite.getMinV(), sprite.getMaxU(), sprite.getMaxV());
//                GlState.enableLighting();
//                flag1 = true;
//            }
//        }

        if (!flag1)
        {
//            if (flag)
//            {
//                drawRect(i, j, i + 16, j + 16, -2130706433);
//                SKC.highlight(i, j, 16, 16);
//            }

            GlState.enableDepth();
            this.itemRender.renderItemAndEffectIntoGUI(itemstack, i, j);
            this.drawnOverlays.add(new Overlay(itemstack, i, j, s));
        }

        this.itemRender.zLevel = 0.0F;
//        this.zLevel = 0.0F;
    }

    private void updateDragSplitting()
    {
        ItemStack itemstack = this.gm.player.inventory.getItemStack();

        if (itemstack != null && this.dragSplitting)
        {
            this.dragSplittingRemnant = itemstack.size;

            for (Slot slot : this.dragSplittingSlots)
            {
                ItemStack itemstack1 = itemstack.copy();
                int i = slot.getStack() == null ? 0 : slot.getStack().size;
                Container.computeStackSize(this.dragSplittingSlots, this.dragSplittingLimit, itemstack1, i);

                if (itemstack1.size > itemstack1.getMaxStackSize())
                {
                    itemstack1.size = itemstack1.getMaxStackSize();
                }

                if (itemstack1.size > slot.getItemStackLimit(itemstack1))
                {
                    itemstack1.size = slot.getItemStackLimit(itemstack1);
                }

                this.dragSplittingRemnant -= itemstack1.size - i;
            }
        }
    }

    /**
     * Returns the slot at the given coordinates or null if there is none.
     */
    private Slot getSlotAtPosition(int x, int y)
    {
        for (int i = 0; i < this.inventorySlots.inventorySlots.size(); ++i)
        {
            Slot slot = (Slot)this.inventorySlots.inventorySlots.get(i);

            if (this.isMouseOverSlot(slot, x, y))
            {
                return slot;
            }
        }

        return null;
    }

    /**
     * Called when the mouse is clicked. Args : mouseX, mouseY, clickedButton
     */
    public void mouseClicked(int mouseX, int mouseY, int mouseButton)
    {
    	if(this.gm == null)
    		return;
    	if(this.cheatStack != null) {
    		Slot slot = this.getSlotAtPosition(mouseX, mouseY);
    		if((mouseButton == 0 || mouseButton == 1) && slot != null && this.gm.player != null && slot.inventory == this.gm.player.inventory)
    			this.gm.player.client.addToSendQueue(new CPacketCheat(this.cheatStack, slot.getIndex(), mouseButton == 0 && this.cheatStack.size > 1));
    		if(mouseButton != 1 && !this.gm.ctrl())
    			this.cheatStack = null;
    		return;
    	}
    	if((mouseButton == 0 || mouseButton == 1 || mouseButton == 2) && this.clickSide(mouseX, mouseY, -1, this.gm.shift() || mouseButton == 1, this.gm.ctrl() || mouseButton == 2))
    		return;
        if(mouseButton == 0) {
        	if(this.gm.itemCheat && this.gm.player != null && this.gm.player.inventory.getItemStack() == null) {
	            for (CheatTab tab : CheatTab.values())
	            {
	                if (this.isInsideTab(tab, mouseX, mouseY))
	                {
	                    this.setCurrentTab(tab);
	                    return;
	                }
	            }
        	}
        }
//        super.mouseClicked(mouseX, mouseY, mouseButton);
//        boolean flag = mouseButton == this.gm.bindTertiary.getKeyCode() + 100;
        Slot slot = this.getSlotAtPosition(mouseX, mouseY);
        long i = System.currentTimeMillis();
        this.doubleClick = this.lastClickSlot == slot && i - this.lastClickTime < 250L && this.lastClickButton == mouseButton;
        this.ignoreMouseUp = false;

        if (mouseButton == 0 || mouseButton == 1) // || flag)
        {
//            int j = this.guiLeft;
//            int k = this.guiTop;
            boolean flag1 = mouseX < 0 || mouseY < 0 || mouseX >= this.xSize || mouseY >= this.ySize;
            int l = -1;

            if (slot != null)
            {
                l = slot.slotNumber;
            }

            if (flag1)
            {
                l = -999;
            }

//            if (this.gm.touchscreen && flag1 && this.gm.thePlayer.inventory.getItemStack() == null)
//            {
//                this.gm.displayGuiScreen((GuiScreen)null);
//                return;
//            }

            if (l != -1)
            {
//                if (this.gm.touchscreen)
//                {
//                    if (slot != null && slot.getHasStack())
//                    {
//                        this.clickedSlot = slot;
//                        this.draggedStack = null;
//                        this.isRightMouseClick = mouseButton == 1;
//                    }
//                    else
//                    {
//                        this.clickedSlot = null;
//                    }
//                }
//                else 
                if (!this.dragSplitting)
                {
                    if (this.gm.player.inventory.getItemStack() == null)
                    {
//                        if (mouseButton == this.gm.bindTertiary.getKeyCode() + 100)
//                        {
//                            this.handleMouseClick(slot, l, mouseButton, 3);
//                        }
//                        else
//                        {
                        boolean flag2 = l != -999 && this.gm.shift();
                        int i1 = 0;

                        if (flag2)
                        {
                            this.shiftClickedSlot = slot != null && slot.getHasStack() ? slot.getStack() : null;
                            i1 = 1;
                        }
                        else if (l == -999)
                        {
                            i1 = 4;
                        }

                        this.handleMouseClick(slot, l, mouseButton, i1);
//                        }

                        this.ignoreMouseUp = true;
                    }
                    else
                    {
                        this.dragSplitting = true;
                        this.dragSplittingButton = mouseButton;
                        this.dragSplittingSlots.clear();

                        if (mouseButton == 0)
                        {
                            this.dragSplittingLimit = 0;
                        }
                        else if (mouseButton == 1)
                        {
                            this.dragSplittingLimit = 1;
                        }
//                        else if (mouseButton == this.gm.bindTertiary.getKeyCode() + 100)
//                        {
//                            this.dragSplittingLimit = 2;
//                        }
                    }
                }
            }
        }

        this.lastClickSlot = slot;
        this.lastClickTime = i;
        this.lastClickButton = mouseButton;
    }

    /**
     * Called when a mouse button is pressed and the mouse is moved around. Parameters are : mouseX, mouseY,
     * lastButtonClicked & timeSinceMouseClick.
     */
    public void mouseDragged(int mouseX, int mouseY)
    {
    	if(this.gm == null || this.cheatStack != null)
    		return;
        Slot slot = this.getSlotAtPosition(mouseX, mouseY);
        ItemStack itemstack = this.gm.player.inventory.getItemStack();

//        if (this.clickedSlot != null && this.gm.touchscreen)
//        {
//            if (clickedMouseButton == 0 || clickedMouseButton == 1)
//            {
//                if (this.draggedStack == null)
//                {
//                    if (slot != this.clickedSlot && this.clickedSlot.getStack() != null)
//                    {
//                        this.draggedStack = this.clickedSlot.getStack().copy();
//                    }
//                }
//                else if (this.draggedStack.stackSize > 1 && slot != null && Container.canAddItemToSlot(slot, this.draggedStack, false))
//                {
//                    long i = this.gm.getSystemTime();
//
//                    if (this.currentDragTargetSlot == slot)
//                    {
//                        if (i - this.dragItemDropDelay > 500L)
//                        {
//                            this.handleMouseClick(this.clickedSlot, this.clickedSlot.slotNumber, 0, 0);
//                            this.handleMouseClick(slot, slot.slotNumber, 1, 0);
//                            this.handleMouseClick(this.clickedSlot, this.clickedSlot.slotNumber, 0, 0);
//                            this.dragItemDropDelay = i + 750L;
//                            --this.draggedStack.stackSize;
//                        }
//                    }
//                    else
//                    {
//                        this.currentDragTargetSlot = slot;
//                        this.dragItemDropDelay = i;
//                    }
//                }
//            }
//        }
//        else
        if (this.dragSplitting && slot != null && itemstack != null && itemstack.size > this.dragSplittingSlots.size() && Container.canAddItemToSlot(slot, itemstack, true) && slot.isItemValid(itemstack) && this.inventorySlots.canDragIntoSlot(slot))
        {
            this.dragSplittingSlots.add(slot);
            this.updateDragSplitting();
        }
    }

    /**
     * Called when a mouse button is released.  Args : mouseX, mouseY, releaseButton
     */
    public void mouseReleased(int mouseX, int mouseY, int state)
    {
    	if(this.gm == null || this.cheatStack != null)
    		return;
        Slot slot = this.getSlotAtPosition(mouseX, mouseY);
//        int i = this.guiLeft;
//        int j = this.guiTop;
        boolean flag = mouseX < 0 || mouseY < 0 || mouseX >= this.xSize || mouseY >= this.ySize;
        int k = -1;

        if (slot != null)
        {
            k = slot.slotNumber;
        }

        if (flag)
        {
            k = -999;
        }

        if (this.doubleClick && slot != null && state == 0 && this.inventorySlots.canMergeSlot((ItemStack)null, slot))
        {
            if (this.gm.shift())
            {
                if (slot != null && slot.inventory != null && this.shiftClickedSlot != null)
                {
                    for (Slot slot2 : this.inventorySlots.inventorySlots)
                    {
                        if (slot2 != null && slot2.canTakeStack(this.gm.player) && slot2.getHasStack() && slot2.inventory == slot.inventory && Container.canAddItemToSlot(slot2, this.shiftClickedSlot, true))
                        {
                            this.handleMouseClick(slot2, slot2.slotNumber, state, 1);
                        }
                    }
                }
            }
            else
            {
                this.handleMouseClick(slot, k, state, 6);
            }

            this.doubleClick = false;
            this.lastClickTime = 0L;
        }
        else
        {
            if (this.dragSplitting && this.dragSplittingButton != state)
            {
                this.dragSplitting = false;
                this.dragSplittingSlots.clear();
                this.ignoreMouseUp = true;
                return;
            }

            if (this.ignoreMouseUp)
            {
                this.ignoreMouseUp = false;
                return;
            }

//            if (this.clickedSlot != null && this.gm.touchscreen)
//            {
//                if (state == 0 || state == 1)
//                {
//                    if (this.draggedStack == null && slot != this.clickedSlot)
//                    {
//                        this.draggedStack = this.clickedSlot.getStack();
//                    }
//
//                    boolean flag2 = Container.canAddItemToSlot(slot, this.draggedStack, false);
//
//                    if (k != -1 && this.draggedStack != null && flag2)
//                    {
//                        this.handleMouseClick(this.clickedSlot, this.clickedSlot.slotNumber, state, 0);
//                        this.handleMouseClick(slot, k, 0, 0);
//
//                        if (this.gm.thePlayer.inventory.getItemStack() != null)
//                        {
//                            this.handleMouseClick(this.clickedSlot, this.clickedSlot.slotNumber, state, 0);
//                            this.touchUpX = mouseX - i;
//                            this.touchUpY = mouseY - j;
//                            this.returningStackDestSlot = this.clickedSlot;
//                            this.returningStack = this.draggedStack;
//                            this.returningStackTime = this.gm.getSystemTime();
//                        }
//                        else
//                        {
//                            this.returningStack = null;
//                        }
//                    }
//                    else if (this.draggedStack != null)
//                    {
//                        this.touchUpX = mouseX - i;
//                        this.touchUpY = mouseY - j;
//                        this.returningStackDestSlot = this.clickedSlot;
//                        this.returningStack = this.draggedStack;
//                        this.returningStackTime = this.gm.getSystemTime();
//                    }
//
//                    this.draggedStack = null;
//                    this.clickedSlot = null;
//                }
//            }
//            else
            if (this.dragSplitting && !this.dragSplittingSlots.isEmpty())
            {
                this.handleMouseClick((Slot)null, -999, Container.getDragCode(0, this.dragSplittingLimit), 5);

                for (Slot slot1 : this.dragSplittingSlots)
                {
                    this.handleMouseClick(slot1, slot1.slotNumber, Container.getDragCode(1, this.dragSplittingLimit), 5);
                }

                this.handleMouseClick((Slot)null, -999, Container.getDragCode(2, this.dragSplittingLimit), 5);
            }
            else if (this.gm.player.inventory.getItemStack() != null)
            {
//                if (state == this.gm.bindTertiary.getKeyCode() + 100)
//                {
//                    this.handleMouseClick(slot, k, state, 3);
//                }
//                else
//                {
                boolean flag1 = k != -999 && this.gm.shift();

                if (flag1)
                {
                    this.shiftClickedSlot = slot != null && slot.getHasStack() ? slot.getStack() : null;
                }

                this.handleMouseClick(slot, k, state, flag1 ? 1 : 0);
//                }
            }
        }

        if (this.gm.player.inventory.getItemStack() == null)
        {
            this.lastClickTime = 0L;
        }

        this.dragSplitting = false;
    }

    /**
     * Returns if the passed mouse position is over the specified slot. Args : slot, mouseX, mouseY
     */
    private boolean isMouseOverSlot(Slot slotIn, int mouseX, int mouseY)
    {
        return this.isPointInRegion(slotIn.xDisplayPosition, slotIn.yDisplayPosition, 16, 16, mouseX, mouseY);
    }

    /**
     * Test if the 2D point is in a rectangle (relative to the GUI). Args : rectX, rectY, rectWidth, rectHeight, pointX,
     * pointY
     */
    protected boolean isPointInRegion(int left, int top, int right, int bottom, int pointX, int pointY)
    {
//        int i = this.guiLeft;
//        int j = this.guiTop;
//        pointX = pointX - i;
//        pointY = pointY - j;
        return pointX >= left - 1 && pointX < left + right + 1 && pointY >= top - 1 && pointY < top + bottom + 1;
    }

    /**
     * Called when the mouse is clicked over a slot or outside the gui.
     */
    protected void handleMouseClick(Slot slotIn, int slotId, int clickedButton, int clickType)
    {
        if (slotIn != null)
        {
            slotId = slotIn.slotNumber;
        }

        this.gm.controller.windowClick(this.inventorySlots.windowId, slotId, clickedButton, clickType, this.gm.player);
    }
    
    public void dropItem() {
    	if (this.gm != null && this.gm.player != null && this.theSlot != null && this.theSlot.getHasStack())
        {
//            if (keyCode == this.gm.bindTertiary.getKeyCode())
//            {
//                this.handleMouseClick(this.theSlot, this.theSlot.slotNumber, 0, 3);
//            }
//            else
//            if (keyCode == this.gm.keyBindDrop.getKeyCode())
//            {
                this.handleMouseClick(this.theSlot, this.theSlot.slotNumber, this.gm.ctrl() ? 1 : 0, 4);
//            }
        }
    }

//    /**
//     * Fired when a key is typed (except F11 which toggles full screen). This is the equivalent of
//     * KeyListener.keyTyped(KeyEvent e). Args : character (character on the key), keyCode (lwjgl Keyboard key code)
//     */
//    protected void keyTyped(char typedChar, int keyCode)
//    {
////        if (keyCode == 1 || keyCode == this.gm.keyBindInventory.getKeyCode())
////        {
////            this.gm.thePlayer.closeScreen();
////        }
//
//        this.checkHotbarKeys(keyCode);
//
//        
//    }

    /**
     * This function is what controls the hotbar shortcut check when you press a number key when hovering a stack. Args
     * : keyCode, Returns true if a Hotbar key is pressed, else false
     */
    public void useHotbar(int slot)
    {
        if (!this.clickSide((this.gm.mouse_x - this.container_x) / 2, (this.gm.mouse_y - this.container_y) / 2, slot, this.gm.shift(), this.gm.ctrl()) && this.gm != null && this.gm.player != null && this.gm.player.inventory.getItemStack() == null && this.cheatStack == null && this.theSlot != null)
        {
//            for (int i = 0; i < 9; ++i)
//            {
//                if (keyCode == this.gm.keyBindsHotbar[i].getKeyCode())
//                {
                    this.handleMouseClick(this.theSlot, this.theSlot.slotNumber, slot, 2);
//                    return true;
//                }
//            }
        }

//        return false;
    }

    /**
     * Called when the screen is unloaded. Used to disable keyboard repeat events
     */
    public void onGuiClosed()
    {
        if (this.gm != null && this.gm.player != null)
        {
            this.inventorySlots.onContainerClosed(this.gm.player);
        }
    }

    /**
     * Returns true if this GUI should pause the game when it is displayed in single-player
     */
//    public boolean doesGuiPauseGame()
//    {
//        return false;
//    }

    /**
     * Called from the main game loop to update the screen.
     */
    public void updateScreen()
    {
//        super.updateScreen();

        if (this.gm != null && this.gm.player != null && (!this.gm.player.isEntityAlive() || this.gm.player.dead))
        {
        	this.gm.displayGuiScreen(null);
        }
    }
    
    public void renderItemOverlayIntoGUI(ItemStack stack, int xPosition, int yPosition, String text)
    {
        renderItemOverlay(stack, this.container_x + xPosition * 2, this.container_y + yPosition * 2, text);
    }
    
    public static void renderItemOverlay(ItemStack stack, int xPosition, int yPosition, String text)
    {
        if (stack != null)
        {
            if (stack.size != 1 || text != null)
            {
                String s = text == null ? ItemStack.formatAmount(stack.size) : text;

                if (text == null && stack.size < 1)
                {
                    s = TextColor.RED + ItemStack.formatAmount(stack.size);
                }
//                this.drawString(s, , );
//                Vec2i size = Drawing.txt_size(0, 0, 0, 0, 65536, 65536, s);
//                int x =  - size.xpos; // this.getStringWidth(s);
//                int y = ;
//        		x = x * 2 + this.container_x;
//        		y = y * 2 + this.container_y;
        		Drawing.drawTextRight(s, xPosition + 32, yPosition + 33 - Font.YGLYPH, 0xffffffff);
            }

            if (stack.isItemDamaged())
            {
                int j = (int)Math.round(28.0D - (double)stack.getItemDamage() * 28.0D / (double)stack.getMaxDamage());
                int i = (int)Math.round(255.0D - (double)stack.getItemDamage() * 255.0D / (double)stack.getMaxDamage());
                draw(xPosition + 2, yPosition + 26, 28, 4, 0, 0, 0);
                draw(xPosition + 2, yPosition + 26, 26, 2, (255 - i) / 4, 64, 0);
                draw(xPosition + 2, yPosition + 26, j, 2, 255 - i, i, 0);
            }
        }
    }
    
    private static void draw(int x, int y, int width, int height, int red, int green, int blue)
    {
//    	Drawing.gfx_draw_rect_color(this.container_x + x * 2, this.container_y + y * 2, width * 2, height * 2, 0xff000000 | (red << 16) | (green << 8) | blue);
    	Drawing.drawRect(x, y, width, height, 0xff000000 | (red << 16) | (green << 8) | blue);
    }
    
    public void drawBackground() {
		Drawing.drawRectBorder(this.container_x, this.container_y, this.container_w, this.container_h, 0xff3f3f3f, 0xff000000, 0xff7f7f7f, 0xff1f1f1f);
    }
    
    
    protected boolean isInsideTab(CheatTab tab, int x, int y)
    {
        return x >= this.xSize + 2 + 18 * tab.getHorizontal() && x < this.xSize + 2 + 18 * tab.getHorizontal() + 18 && 
        	y >= 9 * 18 + 4 + 20 * tab.getVertical() && y < 9 * 18 + 4 + 20 * tab.getVertical() + 18;
    }
    
    protected boolean renderInventoryHoveringText(CheatTab tab, int x, int z)
    {
        if (this.isPointInRegion(this.xSize + 2 + 18 * tab.getHorizontal(), 9 * 18 + 4 + 20 * tab.getVertical(), 18, 18, x, z))
        {
        	this.hover(tab.getName(), x, z);
            return true;
        }
        else
        {
            return false;
        }
    }

    protected void drawTab(CheatTab tab)
    {
        this.itemRender.zLevel = 100.0F;
        ItemStack itemstack = tab.getIcon();
        GlState.enableDepth();
        this.itemRender.renderItemAndEffectIntoGUI(itemstack, this.xSize + 2 + 18 * tab.getHorizontal() + 1, 9 * 18 + 4 + 20 * tab.getVertical() + 1);
        this.itemRender.zLevel = 0.0F;
    }

	public void scroll(int scr_x, int scr_y, int x, int y, boolean ctrl, boolean shift) {
		super.scroll(scr_x, scr_y, x, y, ctrl, shift);
		if(this.gm.itemCheat && scr_y != 0 && this.needsScrollBars()) {
            int len = ITEM_LIST.size() / 12 - 5;
            this.currentScroll = (float)((double)this.currentScroll - (double)scr_y / (double)len);
            this.currentScroll = ExtMath.clampf(this.currentScroll, 0.0F, 1.0F);
        }
	}
    
    private boolean needsScrollBars()
    {
        return ITEM_LIST.size() > 12 * 9;
    }

    private void setCurrentTab(CheatTab tab)
    {
        selectedTab = tab;
        this.dragSplittingSlots.clear();
        ITEM_LIST.clear();
        tab.filter(ITEM_LIST);

        this.currentScroll = 0.0F;
    }
    
    private boolean clickSide(int mouseX, int mouseY, int slot, boolean instant, boolean full) {
        if(this.gm.itemCheat && this.isPointInRegion(this.xSize + 2, 0, 18 * 12, 18 * 9, mouseX, mouseY) && this.gm.player != null && this.gm.player.inventory.getItemStack() == null && this.cheatStack == null) {
            int i = (ITEM_LIST.size() + 12 - 1) / 12 - 9;
            int j = (int)((double)(this.currentScroll * (float)i) + 0.5D);

            if (j < 0)
            {
                j = 0;
            }
            
        	int sx = (mouseX - (this.xSize + 2)) / 18;
        	int sy = mouseY / 18;
            int i1 = sx + (sy + j) * 12;

            if(i1 >= 0 && i1 < ITEM_LIST.size()) {
            	if(slot >= 0 || instant) {
            		this.gm.player.client.addToSendQueue(new CPacketCheat(ITEM_LIST.get(i1), slot, full));
            	}
            	else {
            		this.cheatStack = ITEM_LIST.get(i1).copy();
                    this.cheatStack.size = full ? this.cheatStack.getMaxStackSize() : 1;
            	}
            	return true;
            }
        }
        return false;
    }
}
