package net.minecraft.src;

import java.util.List;

public class PCco_SlotDirectCrafting extends Slot {
	private EntityPlayer thePlayer;
	private ItemStack product;


	public PCco_SlotDirectCrafting(EntityPlayer entityplayer, ItemStack product, int i, int j, int k) {
		super(null, i, j, k);
		thePlayer = entityplayer;
		this.product = product;
	}


	@Override
	public boolean isItemValid(ItemStack itemstack) {
		return false;
	}


	@Override
	public void onPickupFromSlot(ItemStack itemstack) {
		// itemstack.onCrafting(thePlayer.worldObj, thePlayer);
		super.onPickupFromSlot(itemstack);

		doCrafting(product);
	}


	@Override
	public ItemStack decrStackSize(int i) {
		if (isAvailable()) {
			// doCrafting(product);
			return product.copy();
		}
		return null;
	}


	@Override
	public ItemStack getStack() {
		if (isAvailable()) {
			return product.copy();
		}
		return null;
	}


	@Override
	public void putStack(ItemStack itemstack) {
	}


	@Override
	public void onSlotChanged() {
	}


	@Override
	public int getSlotStackLimit() {
		if (product == null) return 1;
		return product.getMaxStackSize();
	}


	private boolean isAvailable() {
		if (product == null) return false;

		if (ModLoader.getMinecraftInstance().playerController.isInCreativeMode() || mod_PCcore.survival_cheating) return true;

		lastRecipe = -1;
		recipeEndReached = false;
		while (true) {
			IRecipe irecipe = getNextRecipeForProduct(product);
			if (irecipe == null || recipeEndReached) return false;
			recursionCount = 0;
			// System.out.println("main recipe is for "+product);
			if (hasPlayerEnoughItemsForRecipe(irecipe)) return true;
		}
	}


	private boolean doCrafting(ItemStack prod) {
		if (prod == null) return false;

		if (ModLoader.getMinecraftInstance().playerController.isInCreativeMode() || mod_PCcore.survival_cheating) return true;

		lastRecipe = -1;
		recipeEndReached = false;
		while (true) {
			IRecipe irecipe = getNextRecipeForProduct(prod);
			if (irecipe == null || recipeEndReached) return false;
			recursionCount = 0;
			if (hasPlayerEnoughItemsForRecipe(irecipe)) {
				recursionCount = 0;
				System.out.println("@@@@@@@ loop1!");
				consumePlayerItemsForRecipe(irecipe);
				return true;
			}
		}
	}


	private boolean countPlayerItems(ItemStack stack1, int count) {
		if (stack1 == null) return true;

		if (ModLoader.getMinecraftInstance().playerController.isInCreativeMode() || mod_PCcore.survival_cheating) return true;

		ItemStack stack = stack1.copy();
		if (stack.getItemDamage() < 0) {
			stack.setItemDamage(0);
		}

		int counter = 0;
		for (int i = 0; i < thePlayer.inventory.getSizeInventory(); i++) {
			ItemStack curStack = thePlayer.inventory.getStackInSlot(i);
			if (curStack != null && (curStack.isItemEqual(stack) || (curStack.itemID == stack1.itemID && stack1.getItemDamage() == -1))) {
				counter += curStack.stackSize;
				if (counter >= count) {
					return true;
				}
			}
		}

		return counter >= count;
	}


	private boolean consumePlayerItems(ItemStack stack1, int count) {

		if (ModLoader.getMinecraftInstance().playerController.isInCreativeMode() || mod_PCcore.survival_cheating) return true;

		if (stack1 == null) return true;
		ItemStack stack = stack1.copy();
		if (stack.getItemDamage() < 0) {
			stack.setItemDamage(0);
		}

		for (int i = 0; i < thePlayer.inventory.getSizeInventory(); i++) {
			ItemStack curStack = thePlayer.inventory.getStackInSlot(i);
			if (curStack != null && (curStack.isItemEqual(stack) || (curStack.itemID == stack1.itemID && stack1.getItemDamage() == -1))) {
				if (curStack.stackSize > count) {
					curStack.stackSize -= count;
					return true;
				} else if (curStack.stackSize <= count) {
					count -= curStack.stackSize;
					thePlayer.inventory.setInventorySlotContents(i, null);
				}
			}
		}
		if (count > 0) {
			return false;
		}
		return true;
	}

	private int lastRecipe = -1;
	private boolean recipeEndReached = false;


	private IRecipe getNextRecipeForProduct(ItemStack prod) {
		List recipes = CraftingManager.getInstance().getRecipeList();

		if (lastRecipe == recipes.size() - 1) return null;

		int k;
		for (k = lastRecipe + 1; k < recipes.size(); k++) {
			IRecipe irecipe = (IRecipe) recipes.get(k);
			try {
				if (irecipe.getCraftingResult(null).isItemEqual(prod)) {
					lastRecipe = k;
					return irecipe;
				}
			} catch (NullPointerException npe) {
				continue;
			}
		}

		recipeEndReached = true;
		lastRecipe = k;
		return null;
	}

	private int recursionCount = 0;


	private boolean hasPlayerEnoughItemsForRecipe(IRecipe irecipe) {
		if (ModLoader.getMinecraftInstance().playerController.isInCreativeMode() || mod_PCcore.survival_cheating) return true;

		recursionCount++;
		if (recursionCount > 10) return false;
		try {

			ItemStack[] tmps;
			if (irecipe instanceof ShapedRecipes) {
				tmps = (ItemStack[]) ModLoader.getPrivateValue(net.minecraft.src.ShapedRecipes.class, irecipe, 2);
			} else if (irecipe instanceof ShapelessRecipes) {
				List<ItemStack> foo = ((List<ItemStack>) ModLoader.getPrivateValue(net.minecraft.src.ShapelessRecipes.class, irecipe, 1));
				tmps = foo.toArray(new ItemStack[foo.size()]);
			} else {
				return false;
			}

			ItemStack[] recipeStacks = new ItemStack[tmps.length];

			for (int i = 0; i < tmps.length; i++) {
				if (tmps[i] != null) recipeStacks[i] = tmps[i].copy();
			}

			// pack similar items to stacks
			for (int i = 0; i < recipeStacks.length; i++) {
				if (recipeStacks[i] != null) {
					for (int j = i + 1; j < recipeStacks.length; j++) {
						if (recipeStacks[j] != null && recipeStacks[j].isItemEqual(recipeStacks[i])) {
							recipeStacks[i].stackSize += recipeStacks[j].stackSize;
							recipeStacks[j] = null;
						}
					}
				}
			}

			for (int i = 0; i < recipeStacks.length; i++) {
				if (recipeStacks[i] == null) continue;
				if (!countPlayerItems(recipeStacks[i], recipeStacks[i].stackSize)) {

					if (!mod_PCcore.recursive_crafting) return false;

					if (recursionCount > 10) return false;

					int id = recipeStacks[i].itemID;

					if (id != mod_PClogic.gateOn.blockID && id != Item.redstoneRepeater.shiftedIndex && id != Block.chest.blockID && id != Block.pressurePlatePlanks.blockID
							&& id != Block.pressurePlateStone.blockID && id != Block.torchRedstoneActive.blockID && id != Block.lever.blockID) return false;

					if (product.getItemDamage() == 19
							&& !((countPlayerItems(new ItemStack(Block.chest.blockID, 1, 0), 1) && (countPlayerItems(new ItemStack(Block.stone.blockID, 1, 0), 2) || countPlayerItems(
									new ItemStack(mod_PClogic.gateOn, 1, 0), 1))) || countPlayerItems(new ItemStack(mod_PClogic.gateOn, 1, 18), 1))) {
						return false;
					}

					int stacked = lastRecipe;

					lastRecipe = -1;

					ItemStack tmp = recipeStacks[i].copy();
					if (tmp.getItemDamage() < 0) {
						tmp.setItemDamage(0);
					}

					// System.out.println("stack "+tmp);
					IRecipe irecipe2 = getNextRecipeForProduct(tmp);
					if (irecipe2 == null) {
						lastRecipe = stacked;
						return false;
					}

					if (hasPlayerEnoughItemsForRecipe(irecipe2)) {
						lastRecipe = stacked;
						return true;
					} else {
						lastRecipe = stacked;
						return false;
					}
				}
			}
			return true;

		} catch (IllegalArgumentException et) {
			et.printStackTrace();
		} catch (SecurityException es) {
			es.printStackTrace();
		} catch (NoSuchFieldException en) {
			en.printStackTrace();
		}
		return false;
	}


	private void consumePlayerItemsForRecipe(IRecipe irecipe) {
		if (ModLoader.getMinecraftInstance().playerController.isInCreativeMode() || mod_PCcore.survival_cheating) return;
		recursionCount++;
		if (recursionCount > 10) return;
		try {
			ItemStack[] tmps;
			if (irecipe instanceof ShapedRecipes) {
				tmps = (ItemStack[]) ModLoader.getPrivateValue(net.minecraft.src.ShapedRecipes.class, irecipe, 2);
			} else if (irecipe instanceof ShapelessRecipes) {
				List<ItemStack> foo = ((List<ItemStack>) ModLoader.getPrivateValue(net.minecraft.src.ShapelessRecipes.class, irecipe, 1));
				tmps = foo.toArray(new ItemStack[foo.size()]);
			} else {
				return;
			}

			ItemStack[] recipeStacks = new ItemStack[tmps.length];
			System.out.println("Crafting " + irecipe.getCraftingResult(null));
			for (int i = 0; i < tmps.length; i++) {
				if (tmps[i] != null) recipeStacks[i] = tmps[i].copy();
				System.out.println("->" + recipeStacks[i]);
			}
			System.out.println("////");
			// pack similar items to stacks
			for (int i = 0; i < recipeStacks.length; i++) {
				if (recipeStacks[i] != null) {
					for (int j = i + 1; j < recipeStacks.length; j++) {
						if (recipeStacks[j] != null && recipeStacks[j].isItemEqual(recipeStacks[i])) {
							recipeStacks[i].stackSize += recipeStacks[j].stackSize;
							recipeStacks[j] = null;
						}
					}
				}
			}

			// consume all items
			for (int i = 0; i < recipeStacks.length; i++) {
				System.out.println("-->" + recipeStacks[i]);
				if (recipeStacks[i] == null) continue;

				if (!consumePlayerItems(recipeStacks[i], recipeStacks[i].stackSize)) {
					if (!mod_PCcore.recursive_crafting) return;

					// doCrafting!

					int id = recipeStacks[i].itemID;
					if (id != mod_PClogic.gateOn.blockID && id != Item.redstoneRepeater.shiftedIndex && id != Block.chest.blockID && id != Block.pressurePlatePlanks.blockID
							&& id != Block.pressurePlateStone.blockID && id != Block.torchRedstoneActive.blockID && id != Block.lever.blockID) return;

					int stacked = lastRecipe;

					lastRecipe = -1;
					ItemStack tmp = recipeStacks[i].copy();
					if (tmp.getItemDamage() < 0) {
						tmp.setItemDamage(0);
					}

					while (true) {

						IRecipe irecipe2 = getNextRecipeForProduct(tmp);
						if (irecipe2 == null) {
							break;
						}

						if (hasPlayerEnoughItemsForRecipe(irecipe2)) {
							System.out.println("##########");
							consumePlayerItemsForRecipe(irecipe2);
							break;
						}
					}

					lastRecipe = stacked;

				}
			}

		} catch (IllegalArgumentException et) {
			et.printStackTrace();
		} catch (SecurityException es) {
			es.printStackTrace();
		} catch (NoSuchFieldException en) {
			en.printStackTrace();
		}
	}

}
