package common.init;

import common.block.Block;
import common.block.BlockDispenser;
import common.block.BlockDynamicLiquid;
import common.block.BlockLiquid;
import common.block.BlockTNT;
import common.color.DyeColor;
import common.dispenser.BehaviorDefaultDispenseItem;
import common.dispenser.BehaviorProjectileDispense;
import common.dispenser.IBehaviorDispenseItem;
import common.dispenser.IBlockSource;
import common.dispenser.IPosition;
import common.entity.Entity;
import common.entity.item.EntityBoat;
import common.entity.item.EntityFireworks;
import common.entity.item.EntityTnt;
import common.entity.item.EntityXpBottle;
import common.entity.projectile.EntityArrow;
import common.entity.projectile.EntityDie;
import common.entity.projectile.EntityDynamite;
import common.entity.projectile.EntityEgg;
import common.entity.projectile.EntityFireCharge;
import common.entity.projectile.EntityPotion;
import common.entity.projectile.EntitySnowball;
import common.entity.types.EntityLiving;
import common.entity.types.IProjectile;
import common.item.Item;
import common.item.ItemBucket;
import common.item.ItemDie;
import common.item.ItemDye;
import common.item.ItemMonsterPlacer;
import common.item.ItemPotion;
import common.item.ItemStack;
import common.material.Material;
import common.rng.Random;
import common.tileentity.TileEntityDispenser;
import common.util.BlockPos;
import common.util.ExtMath;
import common.util.Facing;
import common.world.State;
import common.world.World;

public abstract class DispenserRegistry {
	public static final RegistryDefaulted<Item, IBehaviorDispenseItem> REGISTRY = new RegistryDefaulted<Item, IBehaviorDispenseItem>(new BehaviorDefaultDispenseItem());
	
	static void register() {
		REGISTRY.putObject(Items.arrow, new BehaviorProjectileDispense()
        {
            protected IProjectile getProjectileEntity(World worldIn, IPosition position, ItemStack item)
            {
                EntityArrow entityarrow = new EntityArrow(worldIn, position.getX(), position.getY(), position.getZ());
                entityarrow.canBePickedUp = 1;
                return entityarrow;
            }
        });
		REGISTRY.putObject(Items.egg, new BehaviorProjectileDispense()
        {
            protected IProjectile getProjectileEntity(World worldIn, IPosition position, ItemStack item)
            {
                return new EntityEgg(worldIn, position.getX(), position.getY(), position.getZ());
            }
        });
		REGISTRY.putObject(Items.die, new BehaviorProjectileDispense()
        {
            protected IProjectile getProjectileEntity(World worldIn, IPosition position, ItemStack item)
            {
                return new EntityDie(worldIn, position.getX(), position.getY(), position.getZ(), 
                		ItemDie.DIE_SIDES[ExtMath.clampi(item.getMetadata(), 0, ItemDie.DIE_SIDES.length - 1)]);
            }
            protected float getInaccuracy()
            {
                return super.getInaccuracy() * 5.0F;
            }
            protected float getVelocity()
            {
                return super.getVelocity() * 0.25F;
            }
        });
		REGISTRY.putObject(Items.dynamite, new BehaviorProjectileDispense()
        {
            protected IProjectile getProjectileEntity(World worldIn, IPosition position, ItemStack item)
            {
                return new EntityDynamite(worldIn, position.getX(), position.getY(), position.getZ(), item.getMetadata());
            }
        });
        REGISTRY.putObject(Items.snowball, new BehaviorProjectileDispense()
        {
            protected IProjectile getProjectileEntity(World worldIn, IPosition position, ItemStack item)
            {
                return new EntitySnowball(worldIn, position.getX(), position.getY(), position.getZ());
            }
        });
        REGISTRY.putObject(Items.experience_bottle, new BehaviorProjectileDispense()
        {
            protected IProjectile getProjectileEntity(World worldIn, IPosition position, ItemStack item)
            {
                return new EntityXpBottle(worldIn, position.getX(), position.getY(), position.getZ());
            }
            protected float getInaccuracy()
            {
                return super.getInaccuracy() * 0.5F;
            }
            protected float getVelocity()
            {
                return super.getVelocity() * 1.25F;
            }
        });
        REGISTRY.putObject(Items.potion, new IBehaviorDispenseItem()
        {
            private final BehaviorDefaultDispenseItem field_150843_b = new BehaviorDefaultDispenseItem();
            public ItemStack dispense(IBlockSource source, final ItemStack stack)
            {
                return ItemPotion.isSplash(stack.getMetadata()) ? (new BehaviorProjectileDispense()
                {
                    protected IProjectile getProjectileEntity(World worldIn, IPosition position, ItemStack item)
                    {
                        return new EntityPotion(worldIn, position.getX(), position.getY(), position.getZ(), stack.copy());
                    }
                    protected float getInaccuracy()
                    {
                        return super.getInaccuracy() * 0.5F;
                    }
                    protected float getVelocity()
                    {
                        return super.getVelocity() * 1.25F;
                    }
                }).dispense(source, stack): this.field_150843_b.dispense(source, stack);
            }
        });
        IBehaviorDispenseItem disp = new BehaviorDefaultDispenseItem()
        {
            public ItemStack dispenseStack(IBlockSource source, ItemStack stack)
            {
                Facing enumfacing = BlockDispenser.getFacing(source.getBlockMetadata());
                double d0 = source.getX() + (double)enumfacing.getFrontOffsetX();
                double d1 = (double)((float)source.getBlockPos().getY() + 0.2F);
                double d2 = source.getZ() + (double)enumfacing.getFrontOffsetZ();
                Entity entity = ItemMonsterPlacer.spawnCreature(source.getWorld(), ((ItemMonsterPlacer)stack.getItem()).getSpawnedId(), 
                		d0, d1, d2);

                if (entity instanceof EntityLiving && stack.hasDisplayName())
                {
                    ((EntityLiving)entity).setCustomNameTag(stack.getDisplayName());
                }

                stack.splitStack(1);
                return stack;
            }
        };
        for(EntityEggInfo egg : EntityRegistry.SPAWN_EGGS.values()) {
        	REGISTRY.putObject(ItemRegistry.getRegisteredItem(egg.spawnedID.toLowerCase() + "_spawner"), 
        			disp);
        }
        REGISTRY.putObject(Items.fireworks, new BehaviorDefaultDispenseItem()
        {
            public ItemStack dispenseStack(IBlockSource source, ItemStack stack)
            {
                Facing enumfacing = BlockDispenser.getFacing(source.getBlockMetadata());
                double d0 = source.getX() + (double)enumfacing.getFrontOffsetX();
                double d1 = (double)((float)source.getBlockPos().getY() + 0.2F);
                double d2 = source.getZ() + (double)enumfacing.getFrontOffsetZ();
                EntityFireworks entityfireworkrocket = new EntityFireworks(source.getWorld(), d0, d1, d2, stack);
                source.getWorld().spawnEntityInWorld(entityfireworkrocket);
                stack.splitStack(1);
                return stack;
            }
            protected void playDispenseSound(IBlockSource source)
            {
                source.getWorld().playAuxSFX(1002, source.getBlockPos(), 0);
            }
        });
        REGISTRY.putObject(Items.fire_charge, new BehaviorDefaultDispenseItem()
        {
            public ItemStack dispenseStack(IBlockSource source, ItemStack stack)
            {
                Facing enumfacing = BlockDispenser.getFacing(source.getBlockMetadata());
                IPosition iposition = BlockDispenser.getDispensePosition(source);
                double d0 = iposition.getX() + (double)((float)enumfacing.getFrontOffsetX() * 0.3F);
                double d1 = iposition.getY() + (double)((float)enumfacing.getFrontOffsetY() * 0.3F);
                double d2 = iposition.getZ() + (double)((float)enumfacing.getFrontOffsetZ() * 0.3F);
                World world = source.getWorld();
                Random random = world.rand;
                double d3 = random.gaussian() * 0.05D + (double)enumfacing.getFrontOffsetX();
                double d4 = random.gaussian() * 0.05D + (double)enumfacing.getFrontOffsetY();
                double d5 = random.gaussian() * 0.05D + (double)enumfacing.getFrontOffsetZ();
                world.spawnEntityInWorld(new EntityFireCharge(world, d0, d1, d2, d3, d4, d5));
                stack.splitStack(1);
                return stack;
            }
            protected void playDispenseSound(IBlockSource source)
            {
                source.getWorld().playAuxSFX(1009, source.getBlockPos(), 0);
            }
        });
        REGISTRY.putObject(Items.boat, new BehaviorDefaultDispenseItem()
        {
            private final BehaviorDefaultDispenseItem field_150842_b = new BehaviorDefaultDispenseItem();
            public ItemStack dispenseStack(IBlockSource source, ItemStack stack)
            {
                Facing enumfacing = BlockDispenser.getFacing(source.getBlockMetadata());
                World world = source.getWorld();
                double d0 = source.getX() + (double)((float)enumfacing.getFrontOffsetX() * 1.125F);
                double d1 = source.getY() + (double)((float)enumfacing.getFrontOffsetY() * 1.125F);
                double d2 = source.getZ() + (double)((float)enumfacing.getFrontOffsetZ() * 1.125F);
                BlockPos blockpos = source.getBlockPos().offset(enumfacing);
                Material material = world.getState(blockpos).getBlock().getMaterial();
                double d3;

                if (material.isColdLiquid())
                {
                    d3 = 1.0D;
                }
                else
                {
                    if (!Material.air.equals(material) || !world.getState(blockpos.down()).getBlock().getMaterial().isColdLiquid())
                    {
                        return this.field_150842_b.dispense(source, stack);
                    }

                    d3 = 0.0D;
                }

                EntityBoat entityboat = new EntityBoat(world, d0, d1 + d3, d2);
                world.spawnEntityInWorld(entityboat);
                stack.splitStack(1);
                return stack;
            }
            protected void playDispenseSound(IBlockSource source)
            {
                source.getWorld().playAuxSFX(1000, source.getBlockPos(), 0);
            }
        });
        IBehaviorDispenseItem ibehaviordispenseitem = new BehaviorDefaultDispenseItem()
        {
            private final BehaviorDefaultDispenseItem field_150841_b = new BehaviorDefaultDispenseItem();
            public ItemStack dispenseStack(IBlockSource source, ItemStack stack)
            {
                ItemBucket itembucket = (ItemBucket)stack.getItem();
                BlockPos blockpos = source.getBlockPos().offset(BlockDispenser.getFacing(source.getBlockMetadata()));

                if (itembucket.tryPlaceContainedLiquid(source.getWorld(), blockpos))
                {
                    stack.setItem(Items.bucket);
                    stack.stackSize = 1;
                    return stack;
                }
                else
                {
                    return this.field_150841_b.dispense(source, stack);
                }
            }
        };
//        REGISTRY.putObject(Items.lava_bucket, ibehaviordispenseitem);
//        REGISTRY.putObject(Items.water_bucket, ibehaviordispenseitem);
//        REGISTRY.putObject(Items.fluid_bucket, ibehaviordispenseitem);
		for(int z = 0; z < FluidRegistry.getNumFluids(); z++) {
			REGISTRY.putObject(ItemRegistry.getRegisteredItem(BlockRegistry.REGISTRY.getNameForObject(FluidRegistry.getStaticBlock(z)) + 
					"_bucket"), ibehaviordispenseitem);
		}
        REGISTRY.putObject(Items.bucket, new BehaviorDefaultDispenseItem()
        {
            private final BehaviorDefaultDispenseItem field_150840_b = new BehaviorDefaultDispenseItem();
            public ItemStack dispenseStack(IBlockSource source, ItemStack stack)
            {
                World world = source.getWorld();
                BlockPos blockpos = source.getBlockPos().offset(BlockDispenser.getFacing(source.getBlockMetadata()));
                State iblockstate = world.getState(blockpos);
                Block block = iblockstate.getBlock();
                Material material = block.getMaterial();
                Item item;
//                int meta = 0;

//                if (Material.water.equals(material) && block instanceof BlockLiquid && ((Integer)iblockstate.getValue(BlockLiquid.LEVEL)).intValue() == 0)
//                {
//                    item = Items.water_bucket;
//                }
//                else if (Material.lava.equals(material) && block instanceof BlockLiquid && ((Integer)iblockstate.getValue(BlockLiquid.LEVEL)).intValue() == 0)
//                {
//                    item = Items.lava_bucket;
//                }
//                else
                if (material.isLiquid() && block instanceof BlockLiquid && ((Integer)iblockstate.getValue(BlockLiquid.LEVEL)).intValue() == 0)
                {
                    item = ItemRegistry.getRegisteredItem(BlockRegistry.REGISTRY.getNameForObject(block instanceof BlockDynamicLiquid
                    		? FluidRegistry.getStaticBlock((BlockDynamicLiquid)block) : block) + 
        					"_bucket"); // Items.fluid_bucket;
//                    meta = FluidRegistry.getFluidMeta((BlockLiquid)iblockstate.getBlock());
                }
                else
                {
//                    if (!Material.lava.equals(material) || !(block instanceof BlockLiquid) || ((Integer)iblockstate.getValue(BlockLiquid.LEVEL)).intValue() != 0)
//                    {
                    return super.dispenseStack(source, stack);
//                    }
//
//                    item = Items.lava_bucket;
                }

                world.setBlockToAir(blockpos);

                if (--stack.stackSize == 0)
                {
                    stack.setItem(item);
                    stack.stackSize = 1;
                }
                else if (((TileEntityDispenser)source.getBlockTileEntity()).addItemStack(new ItemStack(item)) < 0)
                {
                    this.field_150840_b.dispense(source, new ItemStack(item, 1, 0));
                }

                return stack;
            }
        });
        REGISTRY.putObject(Items.flint_and_steel, new BehaviorDefaultDispenseItem()
        {
            private boolean field_150839_b = true;
            protected ItemStack dispenseStack(IBlockSource source, ItemStack stack)
            {
                World world = source.getWorld();
                BlockPos blockpos = source.getBlockPos().offset(BlockDispenser.getFacing(source.getBlockMetadata()));

                if (world.isAirBlock(blockpos))
                {
                    world.setState(blockpos, Blocks.fire.getState());

                    if (stack.attemptDamageItem(1, world.rand))
                    {
                        stack.stackSize = 0;
                    }
                }
                else if (world.getState(blockpos).getBlock() == Blocks.tnt)
                {
                    Blocks.tnt.onBlockDestroyedByPlayer(world, blockpos, Blocks.tnt.getState().withProperty(BlockTNT.EXPLODE, Boolean.valueOf(true)));
                    world.setBlockToAir(blockpos);
                }
                else
                {
                    this.field_150839_b = false;
                }

                return stack;
            }
            protected void playDispenseSound(IBlockSource source)
            {
                if (this.field_150839_b)
                {
                    source.getWorld().playAuxSFX(1000, source.getBlockPos(), 0);
                }
                else
                {
                    source.getWorld().playAuxSFX(1001, source.getBlockPos(), 0);
                }
            }
        });
        REGISTRY.putObject(Items.dye, new BehaviorDefaultDispenseItem()
        {
            private boolean field_150838_b = true;
            protected ItemStack dispenseStack(IBlockSource source, ItemStack stack)
            {
                if (DyeColor.WHITE == DyeColor.byDyeDamage(stack.getMetadata()))
                {
                    World world = source.getWorld();
                    BlockPos blockpos = source.getBlockPos().offset(BlockDispenser.getFacing(source.getBlockMetadata()));

                    if (ItemDye.applyBonemeal(stack, world, blockpos))
                    {
                        if (!world.client)
                        {
                            world.playAuxSFX(2005, blockpos, 0);
                        }
                    }
                    else
                    {
                        this.field_150838_b = false;
                    }

                    return stack;
                }
                else
                {
                    return super.dispenseStack(source, stack);
                }
            }
            protected void playDispenseSound(IBlockSource source)
            {
                if (this.field_150838_b)
                {
                    source.getWorld().playAuxSFX(1000, source.getBlockPos(), 0);
                }
                else
                {
                    source.getWorld().playAuxSFX(1001, source.getBlockPos(), 0);
                }
            }
        });
        REGISTRY.putObject(ItemRegistry.getItemFromBlock(Blocks.tnt), new BehaviorDefaultDispenseItem()
        {
            protected ItemStack dispenseStack(IBlockSource source, ItemStack stack)
            {
                World world = source.getWorld();
                BlockPos blockpos = source.getBlockPos().offset(BlockDispenser.getFacing(source.getBlockMetadata()));
                EntityTnt entitytntprimed = new EntityTnt(world, (double)blockpos.getX() + 0.5D, (double)blockpos.getY(), (double)blockpos.getZ() + 0.5D, (EntityLiving)null, stack.getMetadata());
                world.spawnEntityInWorld(entitytntprimed);
                world.playSoundAtEntity(entitytntprimed, SoundEvent.FUSE, 1.0F);
                --stack.stackSize;
                return stack;
            }
        });
//        REGISTRY.putObject(Items.skull, new BehaviorDefaultDispenseItem()
//        {
//            private boolean field_179240_b = true;
//            protected ItemStack dispenseStack(IBlockSource source, ItemStack stack)
//            {
//                World world = source.getWorld();
//                EnumFacing enumfacing = BlockDispenser.getFacing(source.getBlockMetadata());
//                BlockPos blockpos = source.getBlockPos().offset(enumfacing);
//                BlockSkull blockskull = Blocks.skull;
//
//                if (world.isAirBlock(blockpos) && blockskull.canDispenserPlace(world, blockpos, stack))
//                {
//                    if (!world.client)
//                    {
//                        world.setBlockState(blockpos, blockskull.getDefaultState().withProperty(BlockSkull.FACING, EnumFacing.UP), 3);
//                        TileEntity tileentity = world.getTileEntity(blockpos);
//
//                        if (tileentity instanceof TileEntitySkull)
//                        {
//                            if (stack.getMetadata() == 3)
//                            {
//                                String user = null;
//
//                                if (stack.hasTagCompound())
//                                {
//                                    NBTTagCompound nbttagcompound = stack.getTagCompound();
//
//                                    if (nbttagcompound.hasKey("SkullOwner", 8) && nbttagcompound.getString("SkullOwner").length() > 0)
//                                    {
//                                        user = nbttagcompound.getString("SkullOwner");
//                                    }
//                                }
//
//                                ((TileEntitySkull)tileentity).setUser(user);
//                            }
//                            else
//                            {
//                                ((TileEntitySkull)tileentity).setType(stack.getMetadata());
//                            }
//
//                            ((TileEntitySkull)tileentity).setSkullRotation(enumfacing.getOpposite().getHorizontalIndex() * 4);
////                            Blocks.skull.checkWitherSpawn(world, blockpos, (TileEntitySkull)tileentity);
//                        }
//
//                        --stack.stackSize;
//                    }
//                }
//                else
//                {
//                    this.field_179240_b = false;
//                }
//
//                return stack;
//            }
//            protected void playDispenseSound(IBlockSource source)
//            {
//                if (this.field_179240_b)
//                {
//                    source.getWorld().playAuxSFX(1000, source.getBlockPos(), 0);
//                }
//                else
//                {
//                    source.getWorld().playAuxSFX(1001, source.getBlockPos(), 0);
//                }
//            }
//        });
//        REGISTRY.putObject(ItemRegistry.getItemFromBlock(Blocks.pumpkin), new BehaviorDefaultDispenseItem()
//        {
//            private boolean field_179241_b = true;
//            protected ItemStack dispenseStack(IBlockSource source, ItemStack stack)
//            {
//                World world = source.getWorld();
//                BlockPos blockpos = source.getBlockPos().offset(BlockDispenser.getFacing(source.getBlockMetadata()));
//                BlockPumpkin blockpumpkin = (BlockPumpkin)Blocks.pumpkin;
//
//                if (world.isAirBlock(blockpos) && blockpumpkin.canDispenserPlace(world, blockpos))
//                {
//                    if (!world.client)
//                    {
//                        world.setBlockState(blockpos, blockpumpkin.getDefaultState(), 3);
//                    }
//
//                    --stack.stackSize;
//                }
//                else
//                {
//                    this.field_179241_b = false;
//                }
//
//                return stack;
//            }
//            protected void playDispenseSound(IBlockSource source)
//            {
//                if (this.field_179241_b)
//                {
//                    source.getWorld().playAuxSFX(1000, source.getBlockPos(), 0);
//                }
//                else
//                {
//                    source.getWorld().playAuxSFX(1001, source.getBlockPos(), 0);
//                }
//            }
//        });
    }
}
