package org.royaldev.royalcommands.spawninfo;

import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Furnace;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.FurnaceSmeltEvent;
import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.ItemStack;
import org.royaldev.royalcommands.Config;
import org.royaldev.royalcommands.RoyalCommands;
import org.royaldev.royalcommands.data.block.BlockData;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ItemListener implements Listener {

    private final RoyalCommands plugin;

    @SuppressWarnings("unchecked")
    public ItemListener(RoyalCommands instance) {
        plugin = instance;
    }

    @EventHandler(ignoreCancelled = true)
    public void onBlockPlace(BlockPlaceEvent e) {
        if (!Config.itemSpawnTag) return;
        final Block b = e.getBlock();
        final SpawnInfo si = SpawnInfo.SpawnInfoManager.getSpawnInfo(e.getItemInHand());
        if (!si.isSpawned() && !si.hasComponents()) return;
        final BlockData bd = new BlockData(plugin, new BlockData.BlockLocation(b.getLocation()));
        bd.set("spawninfo", si.toString());
        bd.caughtSave();
    }

    @EventHandler(ignoreCancelled = true)
    public void onBlockBreak(BlockBreakEvent e) {
        if (!Config.itemSpawnTag) return;
        final Player p = e.getPlayer();
        final Block b = e.getBlock();
        final BlockData bd = new BlockData(plugin, new BlockData.BlockLocation(b.getLocation()));
        final Object o = bd.get("spawninfo");
        if (o == null) return;
        final SpawnInfo si = new SpawnInfo(o.toString());
        if (!si.isSpawned() && !si.hasComponents()) return;
        e.setCancelled(true);
        final List<ItemStack> drops = Collections.list(Collections.enumeration(b.getDrops(e.getPlayer().getItemInHand())));
        for (int i = 0; i < drops.size(); i++) {
            ItemStack drop = drops.get(i);
            if (drop.getType() != b.getType()) continue;
            drop = SpawnInfo.SpawnInfoManager.applySpawnInfo(drop, si);
            drops.remove(i);
            drops.add(i, drop);
            break;
        }
        b.setType(Material.AIR);
        if (p.getGameMode() != GameMode.CREATIVE) // don't drop blocks in creative mode, obviously
            for (ItemStack drop : drops) b.getWorld().dropItemNaturally(b.getLocation(), drop);
        bd.remove("spawninfo");
        bd.caughtSave();
    }

    @EventHandler(ignoreCancelled = true)
    public void onCraft(CraftItemEvent e) {
        if (!Config.itemSpawnTag) return;
        final CraftingInventory ci = e.getInventory();
        final List<ItemStack> spawnedItems = new ArrayList<ItemStack>();
        for (ItemStack component : ci.getMatrix()) {
            if (component == null) continue;
            final SpawnInfo csi = SpawnInfo.SpawnInfoManager.getSpawnInfo(component);
            if (!csi.isSpawned() && !csi.hasComponents()) continue;
            spawnedItems.add(component);
        }
        if (spawnedItems.isEmpty()) return;
        final SpawnInfo si = SpawnInfo.SpawnInfoManager.getSpawnInfo(ci.getResult());
        si.setHasComponents(true);
        for (ItemStack spawned : spawnedItems) {
            final SpawnInfo ssi = SpawnInfo.SpawnInfoManager.getSpawnInfo(spawned);
            si.getComponents().add(String.format("{(%sx%s):%s}%s%s", spawned.getType().name(), spawned.getAmount(), spawned.getDurability(), ((ssi.isSpawned()) ? " Spawned by: " + ssi.getSpawner() + "." : ""), ((ssi.hasComponents()) ? " Had spawned components." : "")));
        }
        ci.setResult(SpawnInfo.SpawnInfoManager.applySpawnInfo(ci.getResult(), si));
    }

    @EventHandler(ignoreCancelled = true)
    public void onSmelt(FurnaceSmeltEvent e) {
        if (!Config.itemSpawnTag) return;
        final Block b = e.getBlock();
        if (!(b instanceof Furnace)) return;
        final Furnace f = (Furnace) b;
        final SpawnInfo si = SpawnInfo.SpawnInfoManager.getSpawnInfo(e.getResult());
        if (SpawnInfo.SpawnInfoManager.getSpawnInfo(e.getSource()).isSpawned()) {
            if (!si.hasComponents()) si.setHasComponents(true);
            si.getComponents().add(e.getSource().toString());
        }
        if (SpawnInfo.SpawnInfoManager.getSpawnInfo(f.getInventory().getFuel()).isSpawned()) {
            if (!si.hasComponents()) si.setHasComponents(true);
            si.getComponents().add(f.getInventory().getFuel().toString());
        }
        e.setResult(SpawnInfo.SpawnInfoManager.applySpawnInfo(e.getResult(), si));
    }

}

@@ -590,16 +590,58 @@
 Config;%0A
+import org.royaldev.royalcommands.RUtils;%0A
 import o
@@ -2351,16 +2351,38 @@
  drop = 
+RUtils.applySpawnLore(
 SpawnInf
@@ -2424,16 +2424,17 @@
 rop, si)
+)
 ;%0A      

Add lore on spawned item drops