package net.glowstone.net.handler.play.inv;

import com.flowpowered.networking.MessageHandler;
import net.glowstone.EventFactory;
import net.glowstone.constants.ItemIds;
import net.glowstone.entity.GlowPlayer;
import net.glowstone.inventory.GlowInventory;
import net.glowstone.inventory.GlowInventoryView;
import net.glowstone.net.GlowSession;
import net.glowstone.net.message.play.inv.CreativeItemMessage;
import net.glowstone.net.message.play.inv.SetWindowSlotMessage;
import org.bukkit.GameMode;
import org.bukkit.event.inventory.InventoryCreativeEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.InventoryType.SlotType;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;

import java.util.Objects;

public final class CreativeItemHandler implements MessageHandler<GlowSession, CreativeItemMessage> {
    @Override
    public void handle(GlowSession session, CreativeItemMessage message) {
        final GlowPlayer player = session.getPlayer();
        final GlowInventory inv = player.getInventory();
        // CraftBukkit does use a inventory view with both inventories set to the player's inventory
        // for the creative inventory as there is no second inventory (no crafting) visible for the client
        final InventoryView view = new GlowInventoryView(player, InventoryType.CREATIVE, inv, inv);
        final int viewSlot = message.getSlot();
        final int slot = view.convertSlot(viewSlot);
        ItemStack stack = ItemIds.sanitize(message.getItem());
        final SlotType type = inv.getSlotType(slot);

        // only if creative mode
        if (player.getGameMode() != GameMode.CREATIVE) {
            player.kickPlayer("Illegal creative mode item selection");
            return;
        }

        // only if default (player) inventory
        if (!GlowInventoryView.isDefault(player.getOpenInventory())) {
            player.kickPlayer("Illegal creative mode item selection");
            return;
        }

        // clicking outside drops the item
        if (message.getSlot() < 0) {
            InventoryCreativeEvent event = EventFactory.callEvent(new InventoryCreativeEvent(view, SlotType.OUTSIDE, -999, stack));
            if (event.isCancelled()) {
                session.send(new SetWindowSlotMessage(-1, -1, stack));
            } else {
                player.drop(event.getCursor());
            }
            return;
        }

        // if the content hasn't changed, ignore the message
        // this happens quiet often as the client tends to update the whole inventory at once
        if (Objects.equals(stack, view.getItem(viewSlot))) {
            return;
        }

        InventoryCreativeEvent event = EventFactory.callEvent(new InventoryCreativeEvent(view, type, viewSlot, stack));
        if (event.isCancelled()) {
            // send original slot to player to prevent async inventories
            player.sendItemChange(viewSlot, view.getItem(viewSlot));
            // don't keep track of player's current item, just give them back what they tried to place
            session.send(new SetWindowSlotMessage(-1, -1, stack));
            return;
        }

        view.setItem(viewSlot, event.getCursor());
        player.getOpenInventory().setItem(message.getSlot(), message.getItem());
    }
}

@@ -554,57 +554,8 @@
 nt;%0A
-import org.bukkit.event.inventory.InventoryType;%0A
 impo
@@ -1267,70 +1267,32 @@
 w = 
-new GlowInventoryView(player, InventoryType.CREATIVE, inv, inv
+player.getOpenInventory(
 );%0A 
@@ -3135,106 +3135,13 @@
 ot, 
-event.getCursor());%0A        player.getOpenInventory().setItem(message.getSlot(), message.getItem()
+stack
 );%0A 

fix creative inventory bugs