package io.izzel.taboolib.util.item;

import io.izzel.taboolib.util.ArrayUtil;
import org.bukkit.entity.Player;
import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;

/**
 * @Author 坏黑
 * @Since 2019-02-07 23:53
 */
public class ItemStacker {

    /**
     * 从箱子里移动物品到玩家背包
     * 如果溢出则丢弃
     */
    public static void moveItemFromChest(ItemStack item, Player player) {
        AddResult result = addItemAndMerge(item, player.getInventory(), new Integer[0]);
        if (result.countOut > 0) {
            item.setAmount(result.countOut);
            if (!addItemAndSplit(item, player.getInventory(), 0, true)) {
                player.getWorld().dropItem(player.getLocation(), item);
            }
        }
    }

    public static boolean addItemAndSplit(ItemStack item, Inventory inventory, int start) {
        return addItemAndSplit(item, inventory, start, false);
    }

    /**
     * 添加并拆分,但不合并
     * 返回值为是否添加完成
     *
     * desc = 快捷栏逆向添加,用于工作台拟真,会忽略 start 参数
     */
    public static boolean addItemAndSplit(ItemStack item, Inventory inventory, int start, boolean desc) {
        int size = inventory instanceof PlayerInventory || inventory instanceof CraftingInventory ? 36 : inventory.getSize();
        if (desc) {
            // 8 ~ 0
            for (int i = 8; i >= 0; i--) {
                if (check(item, inventory, i)) {
                    return true;
                }
            }
        }
        // 9 ~ 36
        for (int i = desc ? start + 9 : start; i < size; i++) {
            if (check(item, inventory, i)) {
                return true;
            }
        }
        return false;
    }

    public static boolean addItemFromChestToPlayer(ItemStack item, Inventory inventory) {
        for (int i = 8; i >= 0; i--) {
            if (Items.isNull(inventory.getItem(i))) {
                if (item.getAmount() > item.getType().getMaxStackSize()) {
                    ItemStack itemClone = item.clone();
                    itemClone.setAmount(item.getType().getMaxStackSize());
                    inventory.setItem(i, itemClone);
                    item.setAmount(item.getAmount() - item.getType().getMaxStackSize());
                } else {
                    ItemStack itemClone = item.clone();
                    itemClone.setAmount(item.getAmount());
                    inventory.setItem(i, itemClone);
                    item.setAmount(0);
                    return true;
                }
            }
        }
        for (int i = 35; i >= 9; i--) {
            if (Items.isNull(inventory.getItem(i))) {
                if (item.getAmount() > item.getType().getMaxStackSize()) {
                    ItemStack itemClone = item.clone();
                    itemClone.setAmount(item.getType().getMaxStackSize());
                    inventory.setItem(i, itemClone);
                    item.setAmount(item.getAmount() - item.getType().getMaxStackSize());
                } else {
                    ItemStack itemClone = item.clone();
                    itemClone.setAmount(item.getAmount());
                    inventory.setItem(i, itemClone);
                    item.setAmount(0);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 合并物品,不新增
     */
    public static AddResult addItemAndMerge(ItemStack item, Inventory inventory, Integer[] ignore) {
        boolean changed = false;
        int count = item.getAmount();
        int size = inventory instanceof PlayerInventory || inventory instanceof CraftingInventory ? 36 : inventory.getSize();
        for (int i = 0; i < size; i++) {
            if (ArrayUtil.contains(ignore, i)) {
                continue;
            }
            ItemStack inventoryItem = inventory.getItem(i);
            if (!item.isSimilar(inventoryItem)) {
                continue;
            }
            while (count > 0 && inventoryItem.getAmount() < item.getType().getMaxStackSize()) {
                changed = true;
                inventoryItem.setAmount(inventoryItem.getAmount() + 1);
                count--;
            }
            if (count == 0) {
                return new AddResult(count, changed);
            }
        }
        return new AddResult(count, changed);
    }

    private static boolean check(ItemStack item, Inventory inventory, int i) {
        if (Items.isNull(inventory.getItem(i))) {
            // 如果物品数量过多
            if (item.getAmount() > item.getType().getMaxStackSize()) {
                ItemStack itemClone = item.clone();
                itemClone.setAmount(item.getType().getMaxStackSize());
                inventory.setItem(i, itemClone);
                item.setAmount(item.getAmount() - item.getType().getMaxStackSize());
            } else {
                inventory.setItem(i, item.clone());
                item.setAmount(0);
                return true;
            }
        }
        return false;
    }

    public static class AddResult {

        private int countOut;
        private boolean changed;

        public AddResult(int countOut, boolean changed) {
            this.countOut = countOut;
            this.changed = changed;
        }

        public int getCountOut() {
            return countOut;
        }

        public boolean isChanged() {
            return changed;
        }

        @Override
        public String toString() {
            return "AddResult{" +
                    "countOut=" + countOut +
                    ", changed=" + changed +
                    '}';
        }
    }
}