package net.minecraft.block;

import java.util.List;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.state.BlockPistonStructureHelper;
import net.minecraft.block.state.BlockState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityPiston;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

public class BlockPistonBase extends Block
{
    public static final PropertyDirection FACING = PropertyDirection.create("facing");
    public static final PropertyBool EXTENDED = PropertyBool.create("extended");
    /** This piston is the sticky one? */
    private final boolean isSticky;
    private static final String __OBFID = "CL_00000366";

    public BlockPistonBase(boolean p_i45443_1_)
    {
        super(Material.piston);
        this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(EXTENDED, Boolean.valueOf(false)));
        this.isSticky = p_i45443_1_;
        this.setStepSound(soundTypePiston);
        this.setHardness(0.5F);
        this.setCreativeTab(CreativeTabs.tabRedstone);
    }

    public boolean isOpaqueCube()
    {
        return false;
    }

    public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
    {
        worldIn.setBlockState(pos, state.withProperty(FACING, func_180695_a(worldIn, pos, placer)), 2);

        if (!worldIn.isRemote)
        {
            this.func_176316_e(worldIn, pos, state);
        }
    }

    public void onNeighborBlockChange(World worldIn, BlockPos pos, IBlockState state, Block neighborBlock)
    {
        if (!worldIn.isRemote)
        {
            this.func_176316_e(worldIn, pos, state);
        }
    }

    public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state)
    {
        if (!worldIn.isRemote && worldIn.getTileEntity(pos) == null)
        {
            this.func_176316_e(worldIn, pos, state);
        }
    }

    public IBlockState onBlockPlaced(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
    {
        return this.getDefaultState().withProperty(FACING, func_180695_a(worldIn, pos, placer)).withProperty(EXTENDED, Boolean.valueOf(false));
    }

    private void func_176316_e(World worldIn, BlockPos p_176316_2_, IBlockState p_176316_3_)
    {
        EnumFacing enumfacing = (EnumFacing)p_176316_3_.getValue(FACING);
        boolean flag = this.func_176318_b(worldIn, p_176316_2_, enumfacing);

        if (flag && !((Boolean)p_176316_3_.getValue(EXTENDED)).booleanValue())
        {
            if ((new BlockPistonStructureHelper(worldIn, p_176316_2_, enumfacing, true)).func_177253_a())
            {
                worldIn.addBlockEvent(p_176316_2_, this, 0, enumfacing.getIndex());
            }
        }
        else if (!flag && ((Boolean)p_176316_3_.getValue(EXTENDED)).booleanValue())
        {
            worldIn.setBlockState(p_176316_2_, p_176316_3_.withProperty(EXTENDED, Boolean.valueOf(false)), 2);
            worldIn.addBlockEvent(p_176316_2_, this, 1, enumfacing.getIndex());
        }
    }

    private boolean func_176318_b(World worldIn, BlockPos p_176318_2_, EnumFacing p_176318_3_)
    {
        EnumFacing[] aenumfacing = EnumFacing.values();
        int i = aenumfacing.length;
        int j;

        for (j = 0; j < i; ++j)
        {
            EnumFacing enumfacing1 = aenumfacing[j];

            if (enumfacing1 != p_176318_3_ && worldIn.func_175709_b(p_176318_2_.offset(enumfacing1), enumfacing1))
            {
                return true;
            }
        }

        if (worldIn.func_175709_b(p_176318_2_, EnumFacing.NORTH))
        {
            return true;
        }
        else
        {
            BlockPos blockpos1 = p_176318_2_.offsetUp();
            EnumFacing[] aenumfacing1 = EnumFacing.values();
            j = aenumfacing1.length;

            for (int k = 0; k < j; ++k)
            {
                EnumFacing enumfacing2 = aenumfacing1[k];

                if (enumfacing2 != EnumFacing.DOWN && worldIn.func_175709_b(blockpos1.offset(enumfacing2), enumfacing2))
                {
                    return true;
                }
            }

            return false;
        }
    }

    /**
     * Called on both Client and Server when World#addBlockEvent is called
     */
    public boolean onBlockEventReceived(World worldIn, BlockPos pos, IBlockState state, int eventID, int eventParam)
    {
        EnumFacing enumfacing = (EnumFacing)state.getValue(FACING);

        if (!worldIn.isRemote)
        {
            boolean flag = this.func_176318_b(worldIn, pos, enumfacing);

            if (flag && eventID == 1)
            {
                worldIn.setBlockState(pos, state.withProperty(EXTENDED, Boolean.valueOf(true)), 2);
                return false;
            }

            if (!flag && eventID == 0)
            {
                return false;
            }
        }

        if (eventID == 0)
        {
            if (!this.func_176319_a(worldIn, pos, enumfacing, true))
            {
                return false;
            }

            worldIn.setBlockState(pos, state.withProperty(EXTENDED, Boolean.valueOf(true)), 2);
            worldIn.playSoundEffect((double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, "tile.piston.out", 0.5F, worldIn.rand.nextFloat() * 0.25F + 0.6F);
        }
        else if (eventID == 1)
        {
            TileEntity tileentity1 = worldIn.getTileEntity(pos.offset(enumfacing));

            if (tileentity1 instanceof TileEntityPiston)
            {
                ((TileEntityPiston)tileentity1).clearPistonTileEntity();
            }

            worldIn.setBlockState(pos, Blocks.piston_extension.getDefaultState().withProperty(BlockPistonMoving.field_176426_a, enumfacing).withProperty(BlockPistonMoving.field_176425_b, this.isSticky ? BlockPistonExtension.EnumPistonType.STICKY : BlockPistonExtension.EnumPistonType.DEFAULT), 3);
            worldIn.setTileEntity(pos, BlockPistonMoving.func_176423_a(this.getStateFromMeta(eventParam), enumfacing, false, true));

            if (this.isSticky)
            {
                BlockPos blockpos1 = pos.add(enumfacing.getFrontOffsetX() * 2, enumfacing.getFrontOffsetY() * 2, enumfacing.getFrontOffsetZ() * 2);
                Block block = worldIn.getBlockState(blockpos1).getBlock();
                boolean flag1 = false;

                if (block == Blocks.piston_extension)
                {
                    TileEntity tileentity = worldIn.getTileEntity(blockpos1);

                    if (tileentity instanceof TileEntityPiston)
                    {
                        TileEntityPiston tileentitypiston = (TileEntityPiston)tileentity;

                        if (tileentitypiston.func_174930_e() == enumfacing && tileentitypiston.isExtending())
                        {
                            tileentitypiston.clearPistonTileEntity();
                            flag1 = true;
                        }
                    }
                }

                if (!flag1 && block.isAir(worldIn, blockpos1) && func_180696_a(block, worldIn, blockpos1, enumfacing.getOpposite(), false) && (block.getMobilityFlag() == 0 || block == Blocks.piston || block == Blocks.sticky_piston))
                {
                    this.func_176319_a(worldIn, pos, enumfacing, false);
                }
            }
            else
            {
                worldIn.setBlockToAir(pos.offset(enumfacing));
            }

            worldIn.playSoundEffect((double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, "tile.piston.in", 0.5F, worldIn.rand.nextFloat() * 0.15F + 0.6F);
        }

        return true;
    }

    public void setBlockBoundsBasedOnState(IBlockAccess access, BlockPos pos)
    {
        IBlockState iblockstate = access.getBlockState(pos);

        if (iblockstate.getBlock() == this && ((Boolean)iblockstate.getValue(EXTENDED)).booleanValue())
        {
            float f = 0.25F;
            EnumFacing enumfacing = (EnumFacing)iblockstate.getValue(FACING);

            if (enumfacing != null)
            {
                switch (BlockPistonBase.SwitchEnumFacing.field_177243_a[enumfacing.ordinal()])
                {
                    case 1:
                        this.setBlockBounds(0.0F, 0.25F, 0.0F, 1.0F, 1.0F, 1.0F);
                        break;
                    case 2:
                        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.75F, 1.0F);
                        break;
                    case 3:
                        this.setBlockBounds(0.0F, 0.0F, 0.25F, 1.0F, 1.0F, 1.0F);
                        break;
                    case 4:
                        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.75F);
                        break;
                    case 5:
                        this.setBlockBounds(0.25F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
                        break;
                    case 6:
                        this.setBlockBounds(0.0F, 0.0F, 0.0F, 0.75F, 1.0F, 1.0F);
                }
            }
        }
        else
        {
            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
        }
    }

    /**
     * Sets the block's bounds for rendering it as an item
     */
    public void setBlockBoundsForItemRender()
    {
        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
    }

    /**
     * Add all collision boxes of this Block to the list that intersect with the given mask.
     *  
     * @param collidingEntity the Entity colliding with this Block
     */
    public void addCollisionBoxesToList(World worldIn, BlockPos pos, IBlockState state, AxisAlignedBB mask, List list, Entity collidingEntity)
    {
        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
        super.addCollisionBoxesToList(worldIn, pos, state, mask, list, collidingEntity);
    }

    public AxisAlignedBB getCollisionBoundingBox(World worldIn, BlockPos pos, IBlockState state)
    {
        this.setBlockBoundsBasedOnState(worldIn, pos);
        return super.getCollisionBoundingBox(worldIn, pos, state);
    }

    public boolean isFullCube()
    {
        return false;
    }

    public static EnumFacing func_176317_b(int p_176317_0_)
    {
        int j = p_176317_0_ & 7;
        return j > 5 ? null : EnumFacing.getFront(j);
    }

    public static EnumFacing func_180695_a(World worldIn, BlockPos p_180695_1_, EntityLivingBase p_180695_2_)
    {
        if (MathHelper.abs((float)p_180695_2_.posX - (float)p_180695_1_.getX()) < 2.0F && MathHelper.abs((float)p_180695_2_.posZ - (float)p_180695_1_.getZ()) < 2.0F)
        {
            double d0 = p_180695_2_.posY + (double)p_180695_2_.getEyeHeight();

            if (d0 - (double)p_180695_1_.getY() > 2.0D)
            {
                return EnumFacing.UP;
            }

            if ((double)p_180695_1_.getY() - d0 > 0.0D)
            {
                return EnumFacing.DOWN;
            }
        }

        return p_180695_2_.func_174811_aO().getOpposite();
    }

    public static boolean func_180696_a(Block p_180696_0_, World worldIn, BlockPos p_180696_2_, EnumFacing p_180696_3_, boolean p_180696_4_)
    {
        if (p_180696_0_ == Blocks.obsidian)
        {
            return false;
        }
        else if (!worldIn.getWorldBorder().contains(p_180696_2_))
        {
            return false;
        }
        else if (p_180696_2_.getY() >= 0 && (p_180696_3_ != EnumFacing.DOWN || p_180696_2_.getY() != 0))
        {
            if (p_180696_2_.getY() <= worldIn.getHeight() - 1 && (p_180696_3_ != EnumFacing.UP || p_180696_2_.getY() != worldIn.getHeight() - 1))
            {
                if (p_180696_0_ != Blocks.piston && p_180696_0_ != Blocks.sticky_piston)
                {
                    if (p_180696_0_.getBlockHardness(worldIn, p_180696_2_) == -1.0F)
                    {
                        return false;
                    }

                    if (p_180696_0_.getMobilityFlag() == 2)
                    {
                        return false;
                    }

                    if (p_180696_0_.getMobilityFlag() == 1)
                    {
                        if (!p_180696_4_)
                        {
                            return false;
                        }

                        return true;
                    }
                }
                else if (((Boolean)worldIn.getBlockState(p_180696_2_).getValue(EXTENDED)).booleanValue())
                {
                    return false;
                }

                return !(p_180696_0_.hasTileEntity(worldIn.getBlockState(p_180696_2_)));
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

    private boolean func_176319_a(World worldIn, BlockPos p_176319_2_, EnumFacing p_176319_3_, boolean p_176319_4_)
    {
        if (!p_176319_4_)
        {
            worldIn.setBlockToAir(p_176319_2_.offset(p_176319_3_));
        }

        BlockPistonStructureHelper blockpistonstructurehelper = new BlockPistonStructureHelper(worldIn, p_176319_2_, p_176319_3_, p_176319_4_);
        List list = blockpistonstructurehelper.func_177254_c();
        List list1 = blockpistonstructurehelper.func_177252_d();

        if (!blockpistonstructurehelper.func_177253_a())
        {
            return false;
        }
        else
        {
            int i = list.size() + list1.size();
            Block[] ablock = new Block[i];
            EnumFacing enumfacing1 = p_176319_4_ ? p_176319_3_ : p_176319_3_.getOpposite();
            int j;
            BlockPos blockpos1;

            for (j = list1.size() - 1; j >= 0; --j)
            {
                blockpos1 = (BlockPos)list1.get(j);
                Block block = worldIn.getBlockState(blockpos1).getBlock();
                //With our change to how snowballs are dropped this needs to disallow to mimic vanilla behavior.
                float chance = block instanceof BlockSnow ? -1.0f : 1.0f;
                block.dropBlockAsItemWithChance(worldIn, blockpos1, worldIn.getBlockState(blockpos1), chance, 0);
                worldIn.setBlockToAir(blockpos1);
                --i;
                ablock[i] = block;
            }

            IBlockState iblockstate;

            for (j = list.size() - 1; j >= 0; --j)
            {
                blockpos1 = (BlockPos)list.get(j);
                iblockstate = worldIn.getBlockState(blockpos1);
                Block block1 = iblockstate.getBlock();
                block1.getMetaFromState(iblockstate);
                worldIn.setBlockToAir(blockpos1);
                blockpos1 = blockpos1.offset(enumfacing1);
                worldIn.setBlockState(blockpos1, Blocks.piston_extension.getDefaultState().withProperty(FACING, p_176319_3_), 4);
                worldIn.setTileEntity(blockpos1, BlockPistonMoving.func_176423_a(iblockstate, p_176319_3_, p_176319_4_, false));
                --i;
                ablock[i] = block1;
            }

            BlockPos blockpos2 = p_176319_2_.offset(p_176319_3_);

            if (p_176319_4_)
            {
                BlockPistonExtension.EnumPistonType enumpistontype = this.isSticky ? BlockPistonExtension.EnumPistonType.STICKY : BlockPistonExtension.EnumPistonType.DEFAULT;
                iblockstate = Blocks.piston_head.getDefaultState().withProperty(BlockPistonExtension.field_176326_a, p_176319_3_).withProperty(BlockPistonExtension.field_176325_b, enumpistontype);
                IBlockState iblockstate1 = Blocks.piston_extension.getDefaultState().withProperty(BlockPistonMoving.field_176426_a, p_176319_3_).withProperty(BlockPistonMoving.field_176425_b, this.isSticky ? BlockPistonExtension.EnumPistonType.STICKY : BlockPistonExtension.EnumPistonType.DEFAULT);
                worldIn.setBlockState(blockpos2, iblockstate1, 4);
                worldIn.setTileEntity(blockpos2, BlockPistonMoving.func_176423_a(iblockstate, p_176319_3_, true, false));
            }

            int k;

            for (k = list1.size() - 1; k >= 0; --k)
            {
                worldIn.notifyNeighborsOfStateChange((BlockPos)list1.get(k), ablock[i++]);
            }

            for (k = list.size() - 1; k >= 0; --k)
            {
                worldIn.notifyNeighborsOfStateChange((BlockPos)list.get(k), ablock[i++]);
            }

            if (p_176319_4_)
            {
                worldIn.notifyNeighborsOfStateChange(blockpos2, Blocks.piston_head);
                worldIn.notifyNeighborsOfStateChange(p_176319_2_, this);
            }

            return true;
        }
    }

    /**
     * Convert the given metadata into a BlockState for this Block
     */
    public IBlockState getStateFromMeta(int meta)
    {
        return this.getDefaultState().withProperty(FACING, func_176317_b(meta)).withProperty(EXTENDED, Boolean.valueOf((meta & 8) > 0));
    }

    /**
     * Possibly modify the given BlockState before rendering it on an Entity (Minecarts, Endermen, ...)
     */
    @SideOnly(Side.CLIENT)
    public IBlockState getStateForEntityRender(IBlockState state)
    {
        return this.getDefaultState().withProperty(FACING, EnumFacing.UP);
    }

    /**
     * Convert the BlockState into the correct metadata value
     */
    public int getMetaFromState(IBlockState state)
    {
        byte b0 = 0;
        int i = b0 | ((EnumFacing)state.getValue(FACING)).getIndex();

        if (((Boolean)state.getValue(EXTENDED)).booleanValue())
        {
            i |= 8;
        }

        return i;
    }

    protected BlockState createBlockState()
    {
        return new BlockState(this, new IProperty[] {FACING, EXTENDED});
    }

    static final class SwitchEnumFacing
        {
            static final int[] field_177243_a = new int[EnumFacing.values().length];
            private static final String __OBFID = "CL_00002037";

            static
            {
                try
                {
                    field_177243_a[EnumFacing.DOWN.ordinal()] = 1;
                }
                catch (NoSuchFieldError var6)
                {
                    ;
                }

                try
                {
                    field_177243_a[EnumFacing.UP.ordinal()] = 2;
                }
                catch (NoSuchFieldError var5)
                {
                    ;
                }

                try
                {
                    field_177243_a[EnumFacing.NORTH.ordinal()] = 3;
                }
                catch (NoSuchFieldError var4)
                {
                    ;
                }

                try
                {
                    field_177243_a[EnumFacing.SOUTH.ordinal()] = 4;
                }
                catch (NoSuchFieldError var3)
                {
                    ;
                }

                try
                {
                    field_177243_a[EnumFacing.WEST.ordinal()] = 5;
                }
                catch (NoSuchFieldError var2)
                {
                    ;
                }

                try
                {
                    field_177243_a[EnumFacing.EAST.ordinal()] = 6;
                }
                catch (NoSuchFieldError var1)
                {
                    ;
                }
            }
        }
}