/*
 * Copyright (c) 2013 - 2015 xxyy (Philipp Nowak; devnull@nowak-at.net). All rights reserved.
 *
 * Any usage, including, but not limited to, compiling, running, redistributing, printing,
 *  copying and reverse-engineering is strictly prohibited without explicit written permission
 *  from the original author and may result in legal steps being taken.
 *
 * See the included LICENSE file (core/src/main/resources) or email xxyy98+xyclicense@gmail.com for details.
 */

package li.l1t.common.inventory.gui;

import com.google.common.base.Preconditions;
import li.l1t.common.inventory.gui.element.MenuElement;
import li.l1t.common.inventory.gui.holder.SimpleElementHolder;
import li.l1t.common.inventory.gui.util.InvMenuListener;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;

/**
 * A simple implementation of an inventory menu that renders a graphical user interface into a
 * Minecraft inventory. This implementation does not permit hotbar swap. Click events are
 * {@link MenuElement#handleMenuClick(InventoryClickEvent, InventoryMenu)} forwarded} to elements,
 * monitor click and close are ignored. The inventory is created lazily to make sure the
 * inventory title is available.
 *
 * @author <a href="http://xxyy.github.io/">xxyy</a>
 * @since 2016-06-24
 */
public class SimpleInventoryMenu extends SimpleElementHolder implements InventoryMenu {
    private final Plugin plugin;
    private String inventoryTitle;
    private Inventory inventory;
    private Player player;

    /**
     * Creates a new abstract inventory menu.
     * @param plugin the plugin associated with this menu, may not be null
     * @param inventoryTitle the title of the inventory, may not be null
     * @param player the player associated with this menu, may not be null
     */
    protected SimpleInventoryMenu(Plugin plugin, String inventoryTitle, Player player) {
        Preconditions.checkNotNull(plugin, "plugin");
        Preconditions.checkNotNull(inventoryTitle, "inventoryTitle");
        Preconditions.checkNotNull(player, "player");
        this.inventoryTitle = inventoryTitle;
        this.plugin = plugin;
        this.player = player;
        InvMenuListener.register(this);
    }

    @Override
    public void redraw() {
        Inventory inv = getInventory();
        MenuElement[] elementsRaw = getElementsRaw();
        for(int slotId = 0; slotId < INVENTORY_SIZE; slotId++) {
            MenuElement element = elementsRaw[slotId];
            if (element == null) {
                continue;
            }
            ItemStack stack = element.draw(this);
            if(stack == null) {
                stack = placeholder.createStack();
            }
            inv.setItem(slotId, stack);
        }
    }

    @Override
    public void open() {
        redraw();
        if(getPlayer().getOpenInventory() != null) {
            getPlayer().closeInventory();
        }

        getPlayer().openInventory(getInventory());
    }

    @Override
    public void handleClickMonitor(InventoryClickEvent evt) {
        //no-op
    }

    @Override
    public boolean handleClick(InventoryClickEvent evt) {
        int slotId = evt.getSlot();
        if (isOccupied(slotId)) {
            getElementRaw(slotId).handleMenuClick(evt, this);
        }
        return true;
    }

    @Override
    public void handleClose(InventoryCloseEvent evt) {
        //no-op
    }

    @Override
    public boolean permitsHotbarSwap(InventoryClickEvent evt) {
        return false;
    }

    @Override
    public Inventory getInventory() {
        //lazy init to circumvent title possibly being unknown at creation time if overridden
        if (inventory == null) {
            inventory = getPlugin().getServer()
                    .createInventory(this, INVENTORY_SIZE, getInventoryTitle());
        }
        return inventory;
    }

    @Override
    public Plugin getPlugin() {
        return plugin;
    }

    @Override
    public Player getPlayer() {
        return player;
    }

    @Override
    public String getInventoryTitle() {
        return inventoryTitle;
    }
}

@@ -1174,18 +1174,18 @@
  are
-%0A *
  %7B@link
+%0A *
  Men
@@ -1273,19 +1273,16 @@
 nts,
-%0A *
  monitor
  cli
@@ -1277,16 +1277,19 @@
  monitor
+%0A *
  click a
@@ -1358,19 +1358,16 @@
 sure the
-%0A *
  invento
@@ -1377,16 +1377,19 @@
 title is
+%0A *
  availab
@@ -1744,16 +1744,23 @@
 y menu.%0A
+     *%0A
      * @
@@ -1772,16 +1772,24 @@
  plugin 
+        
 the plug
@@ -1928,16 +1928,24 @@
  player 
+        
 the play
@@ -2099,34 +2099,12 @@
     
-Preconditions.checkNotNull
+this
 (plu
@@ -2112,16 +2112,14 @@
 in, 
-%22
 pl
-ugin%22
+ayer
 );%0A 
@@ -2116,32 +2116,54 @@
 player);%0A       
+ this.inventoryTitle =
  Preconditions.c
@@ -2217,162 +2217,531 @@
     
+%7D%0A%0A
     
-Preconditions.checkNotNull(
+/**%0A     * Creates a new abstract inventory menu without a title. When using this constructor, %7B@link%0A     * #getInventoryTitle()%7D must be overridden.%0A     *%0A     * @param plugin the plugin associated with this menu, may not be null%0A     * @param 
 player
-, %22
+ the 
 player
-%22);%0A        this.inventoryTitle = inventoryTitle;%0A        this.plugin = plugin;%0A        this.player = player
+ associated with this menu, may not be null%0A     */%0A    protected SimpleInventoryMenu(Plugin plugin, Player player) %7B%0A        this.plugin = Preconditions.checkNotNull(plugin, %22plugin%22);%0A        this.player = Preconditions.checkNotNull(player, %22player%22)
 ;%0A  
@@ -2931,16 +2931,17 @@
      for
+ 
 (int slo
@@ -3180,16 +3180,17 @@
       if
+ 
 (stack =
@@ -3388,16 +3388,17 @@
       if
+ 
 (getPlay
@@ -3648,32 +3648,104 @@
 %0A%0A    @Override%0A
+    @SuppressWarnings(%22unchecked%22) //Java needs self-types for generics%0A
     public boole
@@ -4708,24 +4708,262 @@
 ryTitle() %7B%0A
+        if (inventoryTitle == null) %7B%0A            throw new AssertionError(%22If no inventory title is passed, %22 +%0A                    %22SimpleInventoryMenu#getInventoryTitle() must be overridden! (%22 + getClass().getName() + %22)%22);%0A        %7D%0A
         retu

Allow SimpleInventoryMenu subclasses to generate title dynamically