package crazypants.enderio.machine.buffer;

import net.minecraft.block.Block;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IIcon;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import crazypants.enderio.EnderIO;
import crazypants.enderio.GuiHandler;
import crazypants.enderio.ModObject;
import crazypants.enderio.machine.AbstractMachineBlock;
import crazypants.enderio.machine.MachineRecipeInput;
import crazypants.enderio.machine.MachineRecipeRegistry;
import crazypants.enderio.machine.painter.BasicPainterTemplate;
import crazypants.enderio.machine.painter.PainterUtil;
import crazypants.enderio.network.PacketHandler;
import crazypants.util.IFacade;

public class BlockBuffer extends AbstractMachineBlock<TileBuffer> implements IFacade {

  public static BlockBuffer create() {
    PacketHandler.INSTANCE.registerMessage(PacketBufferIO.class, PacketBufferIO.class, PacketHandler.nextID(), Side.SERVER);
    BlockBuffer res = new BlockBuffer();
    res.init();
    return res;
  }

  private static final String[] textureNames = new String[] { "blockBufferItem", "blockBufferPower", "blockBufferOmni", "blockBufferCreative" };
  @SideOnly(Side.CLIENT)
  private IIcon[] textures;

  private BlockBuffer() {
    super(ModObject.blockBuffer, TileBuffer.class);
  }

  @Override
  protected void init() {
    GameRegistry.registerBlock(this, BlockItemBuffer.class, modObject.unlocalisedName);
    GameRegistry.registerTileEntity(teClass, modObject.unlocalisedName + "TileEntity");
    EnderIO.guiHandler.registerGuiHandler(getGuiId(), this);
    MachineRecipeRegistry.instance.registerRecipe(ModObject.blockPainter.unlocalisedName, new PainterTemplate());
  }

  @Override
  public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(te instanceof TileBuffer) {
      return new ContainerBuffer(player.inventory, (TileBuffer) te);
    }
    return null;
  }

  @Override
  public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(te instanceof TileBuffer) {
      return new GuiBuffer(player.inventory, (TileBuffer) te);
    }
    return null;
  }

  @Override
  protected int getGuiId() {
    return GuiHandler.GUI_ID_BUFFER;
  }

  @Override
  @SideOnly(Side.CLIENT)
  public void registerBlockIcons(IIconRegister iIconRegister) {
    super.registerBlockIcons(iIconRegister);
    textures = new IIcon[textureNames.length];
    for (int i = 0; i < textureNames.length; i++) {
      textures[i] = iIconRegister.registerIcon("enderio:" + textureNames[i]);
    }
  }

  @Override
  protected String getMachineFrontIconKey(boolean active) {
    return getSideIconKey(active);
  }

  @Override
  @SideOnly(Side.CLIENT)
  public IIcon getIcon(int blockSide, int blockMeta) {
    return blockSide > 1 ? textures[blockMeta] : super.getIcon(blockSide, blockMeta);
  }

  @Override
  @SideOnly(Side.CLIENT)
  public IIcon getIcon(IBlockAccess world, int x, int y, int z, int blockSide) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(te instanceof TileBuffer) {
      TileBuffer tef = (TileBuffer) te;
      if(tef.getSourceBlock() != null) {
        return tef.getSourceBlock().getIcon(blockSide, tef.getSourceBlockMetadata());
      } else if(blockSide > 1) {
        return textures[world.getBlockMetadata(x, y, z)];
      }
    }
    return super.getIcon(world, x, y, z, blockSide);
  }

  @Override
  public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase entity, ItemStack stack) {
    if(entity instanceof EntityPlayer) {
      TileEntity te = world.getTileEntity(x, y, z);
      if(te instanceof TileBuffer) {
        TileBuffer ta = (TileBuffer) te;
        if(stack.stackTagCompound != null) {
          ta.readCommon(stack.stackTagCompound);
        }
        world.markBlockForUpdate(x, y, z);
      }
    }
  }

  @Override
  public int damageDropped(int meta) {
    return meta;
  }

  // TODO refactor machines so all have this functionality
  @Override
  public ItemStack getPickBlock(MovingObjectPosition target, World world, int x, int y, int z) {
    return createDrop((TileBuffer) world.getTileEntity(x, y, z));
  }

  private ItemStack createDrop(TileBuffer te) {
    ItemStack stack = new ItemStack(this, 1, BlockItemBuffer.Type.get(te).ordinal());
    stack.stackTagCompound = new NBTTagCompound();
    te.writeCommon(stack.stackTagCompound);
    return stack;
  }

  public ItemStack createItemStackForSourceBlock(ItemStack machine, Block block, int sourceMeta) {
    PainterUtil.setSourceBlock(machine, block, sourceMeta);
    return machine;
  }

  public final class PainterTemplate extends BasicPainterTemplate {

    public PainterTemplate() {
      super(BlockBuffer.this);
    }

    @Override
    public ResultStack[] getCompletedResult(float chance, MachineRecipeInput... inputs) {
      ItemStack paintSource = MachineRecipeInput.getInputForSlot(1, inputs);
      if(paintSource == null) {
        return new ResultStack[0];
      }
      return new ResultStack[] { new ResultStack(createItemStackForSourceBlock(MachineRecipeInput.getInputForSlot(0, inputs).copy(),
          Block.getBlockFromItem(paintSource.getItem()), paintSource.getItemDamage())) };
    }
  }

  @Override
  public int getFacadeMetadata(IBlockAccess world, int x, int y, int z, int side) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(te instanceof TileBuffer) {
      return ((TileBuffer) te).getSourceBlockMetadata();
    }
    return 0;
  }

  @Override
  public Block getFacade(IBlockAccess world, int x, int y, int z, int side) {
    TileEntity te = world.getTileEntity(x, y, z);
    if(te instanceof TileBuffer) {
      return ((TileBuffer) te).getSourceBlock();
    }
    return this;
  }

}

@@ -5540,24 +5540,154 @@
 0%5D;%0A      %7D%0A
+      ItemStack target = MachineRecipeInput.getInputForSlot(0, inputs);%0A      target = target.copy();%0A      target.stackSize = 1;%0A
       return
@@ -5757,71 +5757,15 @@
 ock(
-MachineRecipeInput.getInputForSlot(0, inputs).copy(),%0A         
+target,
  Blo
@@ -5807,16 +5807,26 @@
 Item()),
+%0A         
  paintSo

Fix odd dupe bug when painting buffers