package common.block.artificial;

import common.block.Block;
import common.block.Rotatable;
import common.block.Material;
import common.entity.npc.EntityNPC;
import common.entity.types.EntityLiving;
import common.init.Blocks;
import common.init.WoodType;
import common.item.CheatTab;
import common.model.Model;
import common.model.ModelProvider;
import common.model.ModelRotation;
import common.model.Transforms;
import common.properties.Property;
import common.properties.PropertyBool;
import common.util.BlockPos;
import common.util.BoundingBox;
import common.util.Facing;
import common.world.IBlockAccess;
import common.world.IWorldAccess;
import common.world.State;
import common.world.World;

public class BlockFenceGate extends Block implements Rotatable
{
    public static final PropertyBool OPEN = PropertyBool.create("open");
    public static final PropertyBool POWERED = PropertyBool.create("powered");
    public static final PropertyBool IN_WALL = PropertyBool.create("in_wall");
    
    private final String texture;

    public BlockFenceGate(WoodType p_i46394_1_)
    {
        super(Material.WOOD); // , p_i46394_1_.getMapColor());
        this.setDefaultState(this.getBaseState().withProperty(OPEN, Boolean.valueOf(false)).withProperty(POWERED, Boolean.valueOf(false)).withProperty(IN_WALL, Boolean.valueOf(false)));
        this.setTab(CheatTab.WOOD);
        this.texture = p_i46394_1_.getName() + "_planks";
    }

    /**
     * Get the actual Block state of this Block at the given position. This applies properties not visible in the
     * metadata, such as fence connections.
     */
    public State getActualState(State state, IWorldAccess worldIn, BlockPos pos)
    {
        Facing.Axis enumfacing$axis = ((Facing)state.getValue(FACING)).getAxis();

        if (enumfacing$axis == Facing.Axis.Z && (worldIn.getState(pos.west()).getBlock() == Blocks.cobblestone_wall || worldIn.getState(pos.east()).getBlock() == Blocks.cobblestone_wall) || enumfacing$axis == Facing.Axis.X && (worldIn.getState(pos.north()).getBlock() == Blocks.cobblestone_wall || worldIn.getState(pos.south()).getBlock() == Blocks.cobblestone_wall))
        {
            state = state.withProperty(IN_WALL, Boolean.valueOf(true));
        }

        return state;
    }

    public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
    {
        return worldIn.getState(pos.down()).getBlock().getMaterial().isSolid() ? super.canPlaceBlockAt(worldIn, pos) : false;
    }

    public BoundingBox getCollisionBoundingBox(World worldIn, BlockPos pos, State state)
    {
        if (((Boolean)state.getValue(OPEN)).booleanValue())
        {
            return null;
        }
        else
        {
            Facing.Axis enumfacing$axis = ((Facing)state.getValue(FACING)).getAxis();
            return enumfacing$axis == Facing.Axis.Z ? new BoundingBox((double)pos.getX(), (double)pos.getY(), (double)((float)pos.getZ() + 0.375F), (double)(pos.getX() + 1), (double)((float)pos.getY() + 1.5F), (double)((float)pos.getZ() + 0.625F)) : new BoundingBox((double)((float)pos.getX() + 0.375F), (double)pos.getY(), (double)pos.getZ(), (double)((float)pos.getX() + 0.625F), (double)((float)pos.getY() + 1.5F), (double)(pos.getZ() + 1));
        }
    }

    public void setBlockBoundsBasedOnState(IWorldAccess worldIn, BlockPos pos)
    {
        Facing.Axis enumfacing$axis = ((Facing)worldIn.getState(pos).getValue(FACING)).getAxis();

        if (enumfacing$axis == Facing.Axis.Z)
        {
            this.setBlockBounds(0.0F, 0.0F, 0.375F, 1.0F, 1.0F, 0.625F);
        }
        else
        {
            this.setBlockBounds(0.375F, 0.0F, 0.0F, 0.625F, 1.0F, 1.0F);
        }
    }

    /**
     * Used to determine ambient occlusion and culling when rebuilding chunks for render
     */
    public boolean isOpaqueCube()
    {
        return false;
    }

    public boolean isFullCube()
    {
        return false;
    }

    public boolean isPassable(IBlockAccess worldIn, BlockPos pos)
    {
        return ((Boolean)worldIn.getState(pos).getValue(OPEN)).booleanValue();
    }

    /**
     * Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the
     * IBlockstate
     */
    public State onBlockPlaced(World worldIn, BlockPos pos, Facing facing, float hitX, float hitY, float hitZ, EntityLiving placer)
    {
        return this.getState().withProperty(FACING, placer.getHorizontalFacing()).withProperty(OPEN, Boolean.valueOf(false)).withProperty(POWERED, Boolean.valueOf(false)).withProperty(IN_WALL, Boolean.valueOf(false));
    }

    public boolean onBlockActivated(World worldIn, BlockPos pos, State state, EntityNPC playerIn, Facing side, float hitX, float hitY, float hitZ)
    {
        if (((Boolean)state.getValue(OPEN)).booleanValue())
        {
            state = state.withProperty(OPEN, Boolean.valueOf(false));
            worldIn.setState(pos, state, 2);
        }
        else
        {
            Facing enumfacing = Facing.fromAngle((double)playerIn.rotYaw);

            if (state.getValue(FACING) == enumfacing.getOpposite())
            {
                state = state.withProperty(FACING, enumfacing);
            }

            state = state.withProperty(OPEN, Boolean.valueOf(true));
            worldIn.setState(pos, state, 2);
        }

        worldIn.playAuxSFX(playerIn, ((Boolean)state.getValue(OPEN)).booleanValue() ? 1003 : 1006, pos, 0);
        return true;
    }

    /**
     * Called when a neighboring block changes.
     */
    public void onNeighborBlockChange(World worldIn, BlockPos pos, State state, Block neighborBlock)
    {
        if (!worldIn.client)
        {
            boolean flag = worldIn.isBlockPowered(pos);

            if (flag || neighborBlock.canProvidePower())
            {
                if (flag && !((Boolean)state.getValue(OPEN)).booleanValue() && !((Boolean)state.getValue(POWERED)).booleanValue())
                {
                    worldIn.setState(pos, state.withProperty(OPEN, Boolean.valueOf(true)).withProperty(POWERED, Boolean.valueOf(true)), 2);
                    worldIn.playAuxSFX(1003, pos, 0);
                }
                else if (!flag && ((Boolean)state.getValue(OPEN)).booleanValue() && ((Boolean)state.getValue(POWERED)).booleanValue())
                {
                    worldIn.setState(pos, state.withProperty(OPEN, Boolean.valueOf(false)).withProperty(POWERED, Boolean.valueOf(false)), 2);
                    worldIn.playAuxSFX(1006, pos, 0);
                }
                else if (flag != ((Boolean)state.getValue(POWERED)).booleanValue())
                {
                    worldIn.setState(pos, state.withProperty(POWERED, Boolean.valueOf(flag)), 2);
                }
            }
        }
    }

    public boolean shouldSideBeRendered(IWorldAccess worldIn, BlockPos pos, Facing side)
    {
        return true;
    }

    /**
     * Convert the given metadata into a BlockState for this Block
     */
    public State getStateFromMeta(int meta)
    {
        return this.getState().withProperty(FACING, Facing.getHorizontal(meta)).withProperty(OPEN, Boolean.valueOf((meta & 4) != 0)).withProperty(POWERED, Boolean.valueOf((meta & 8) != 0));
    }

    /**
     * Convert the BlockState into the correct metadata value
     */
    public int getMetaFromState(State state)
    {
        int i = 0;
        i = i | ((Facing)state.getValue(FACING)).getHorizontalIndex();

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

        if (((Boolean)state.getValue(OPEN)).booleanValue())
        {
            i |= 4;
        }

        return i;
    }

    protected Property[] getProperties()
    {
        return new Property[] {FACING, OPEN, POWERED, IN_WALL};
    }

    public Transforms getTransform() {
    	return Transforms.GATE;
    }

    public Model getModel(ModelProvider provider, String name, State state) {
    	return (state.getValue(IN_WALL) ? (state.getValue(OPEN) ? provider.getModel(this.texture).uvLock()
			.add(0, 2, 7, 2, 13, 9)
				.d().uv(0, 7, 2, 9).noCull()
				.u().uv(0, 7, 2, 9).noCull()
				.n().uv(0, 0, 2, 11).noCull()
				.s().uv(0, 0, 2, 11).noCull()
				.w().uv(7, 0, 9, 11)
				.e().uv(7, 0, 9, 11).noCull()
			.add(14, 2, 7, 16, 13, 9)
				.d().uv(14, 7, 16, 9).noCull()
				.u().uv(14, 7, 16, 9).noCull()
				.n().uv(14, 0, 16, 11).noCull()
				.s().uv(14, 0, 16, 11).noCull()
				.w().uv(7, 0, 9, 11).noCull()
				.e().uv(7, 0, 9, 11)
			.add(0, 3, 13, 2, 12, 15)
				.d().uv(0, 13, 2, 15).noCull()
				.u().uv(0, 13, 2, 15).noCull()
				.n().uv(0, 1, 2, 10).noCull()
				.s().uv(0, 1, 2, 10).noCull()
				.w().uv(13, 1, 15, 10).noCull()
				.e().uv(13, 1, 15, 10).noCull()
			.add(14, 3, 13, 16, 12, 15)
				.d().uv(14, 13, 16, 15).noCull()
				.u().uv(14, 13, 16, 15).noCull()
				.n().uv(14, 1, 16, 10).noCull()
				.s().uv(14, 1, 16, 10).noCull()
				.w().uv(13, 1, 15, 10).noCull()
				.e().uv(13, 1, 15, 10).noCull()
			.add(0, 3, 9, 2, 6, 13)
				.d().uv(0, 9, 2, 13).noCull()
				.u().uv(0, 9, 2, 13).noCull()
				.w().uv(13, 7, 15, 10).noCull()
				.e().uv(13, 7, 15, 10).noCull()
			.add(0, 9, 9, 2, 12, 13)
				.d().uv(0, 9, 2, 13).noCull()
				.u().uv(0, 9, 2, 13).noCull()
				.w().uv(13, 1, 15, 4).noCull()
				.e().uv(13, 1, 15, 4).noCull()
			.add(14, 3, 9, 16, 6, 13)
				.d().uv(14, 9, 16, 13).noCull()
				.u().uv(14, 9, 16, 13).noCull()
				.w().uv(13, 7, 15, 10).noCull()
				.e().uv(13, 7, 15, 10).noCull()
			.add(14, 9, 9, 16, 12, 13)
				.d().uv(14, 9, 16, 13).noCull()
				.u().uv(14, 9, 16, 13).noCull()
				.w().uv(13, 1, 15, 4).noCull()
				.e().uv(13, 1, 15, 4).noCull() : provider.getModel(this.texture).uvLock()
			.add(0, 2, 7, 2, 13, 9)
				.d().uv(0, 7, 2, 9).noCull()
				.u().uv(0, 7, 2, 9).noCull()
				.n().uv(0, 0, 2, 11).noCull()
				.s().uv(0, 0, 2, 11).noCull()
				.w().uv(7, 0, 9, 11)
				.e().uv(7, 0, 9, 11).noCull()
			.add(14, 2, 7, 16, 13, 9)
				.d().uv(14, 7, 16, 9).noCull()
				.u().uv(14, 7, 16, 9).noCull()
				.n().uv(14, 0, 16, 11).noCull()
				.s().uv(14, 0, 16, 11).noCull()
				.w().uv(7, 0, 9, 11).noCull()
				.e().uv(7, 0, 9, 11)
			.add(6, 3, 7, 8, 12, 9)
				.d().uv(6, 7, 8, 9).noCull()
				.u().uv(6, 7, 8, 9).noCull()
				.n().uv(6, 1, 8, 10).noCull()
				.s().uv(6, 1, 8, 10).noCull()
				.w().uv(7, 1, 9, 10).noCull()
				.e().uv(7, 1, 9, 10).noCull()
			.add(8, 3, 7, 10, 12, 9)
				.d().uv(8, 7, 10, 9).noCull()
				.u().uv(8, 7, 10, 9).noCull()
				.n().uv(8, 1, 10, 10).noCull()
				.s().uv(8, 1, 10, 10).noCull()
				.w().uv(7, 1, 9, 10).noCull()
				.e().uv(7, 1, 9, 10).noCull()
			.add(2, 3, 7, 6, 6, 9)
				.d().uv(2, 7, 6, 9).noCull()
				.u().uv(2, 7, 6, 9).noCull()
				.n().uv(2, 7, 6, 10).noCull()
				.s().uv(2, 7, 6, 10).noCull()
			.add(2, 9, 7, 6, 12, 9)
				.d().uv(2, 7, 6, 9).noCull()
				.u().uv(2, 7, 6, 9).noCull()
				.n().uv(2, 1, 6, 4).noCull()
				.s().uv(2, 1, 6, 4).noCull()
			.add(10, 3, 7, 14, 6, 9)
				.d().uv(10, 7, 14, 9).noCull()
				.u().uv(10, 7, 14, 9).noCull()
				.n().uv(10, 7, 14, 10).noCull()
				.s().uv(10, 7, 14, 10).noCull()
			.add(10, 9, 7, 14, 12, 9)
				.d().uv(10, 7, 14, 9).noCull()
				.u().uv(10, 7, 14, 9).noCull()
				.n().uv(10, 1, 14, 4).noCull()
				.s().uv(10, 1, 14, 4).noCull()) : (state.getValue(OPEN) ? provider.getModel(this.texture).uvLock()
			.add(0, 5, 7, 2, 16, 9)
				.d().uv(0, 7, 2, 9).noCull()
				.u().uv(0, 7, 2, 9).noCull()
				.n().uv(0, 0, 2, 11).noCull()
				.s().uv(0, 0, 2, 11).noCull()
				.w().uv(7, 0, 9, 11)
				.e().uv(7, 0, 9, 11).noCull()
			.add(14, 5, 7, 16, 16, 9)
				.d().uv(14, 7, 16, 9).noCull()
				.u().uv(14, 7, 16, 9).noCull()
				.n().uv(14, 0, 16, 11).noCull()
				.s().uv(14, 0, 16, 11).noCull()
				.w().uv(7, 0, 9, 11).noCull()
				.e().uv(7, 0, 9, 11)
			.add(0, 6, 13, 2, 15, 15)
				.d().uv(0, 13, 2, 15).noCull()
				.u().uv(0, 13, 2, 15).noCull()
				.n().uv(0, 1, 2, 10).noCull()
				.s().uv(0, 1, 2, 10).noCull()
				.w().uv(13, 1, 15, 10).noCull()
				.e().uv(13, 1, 15, 10).noCull()
			.add(14, 6, 13, 16, 15, 15)
				.d().uv(14, 13, 16, 15).noCull()
				.u().uv(14, 13, 16, 15).noCull()
				.n().uv(14, 1, 16, 10).noCull()
				.s().uv(14, 1, 16, 10).noCull()
				.w().uv(13, 1, 15, 10).noCull()
				.e().uv(13, 1, 15, 10).noCull()
			.add(0, 6, 9, 2, 9, 13)
				.d().uv(0, 9, 2, 13).noCull()
				.u().uv(0, 9, 2, 13).noCull()
				.w().uv(13, 7, 15, 10).noCull()
				.e().uv(13, 7, 15, 10).noCull()
			.add(0, 12, 9, 2, 15, 13)
				.d().uv(0, 9, 2, 13).noCull()
				.u().uv(0, 9, 2, 13).noCull()
				.w().uv(13, 1, 15, 4).noCull()
				.e().uv(13, 1, 15, 4).noCull()
			.add(14, 6, 9, 16, 9, 13)
				.d().uv(14, 9, 16, 13).noCull()
				.u().uv(14, 9, 16, 13).noCull()
				.w().uv(13, 7, 15, 10).noCull()
				.e().uv(13, 7, 15, 10).noCull()
			.add(14, 12, 9, 16, 15, 13)
				.d().uv(14, 9, 16, 13).noCull()
				.u().uv(14, 9, 16, 13).noCull()
				.w().uv(13, 1, 15, 4).noCull()
				.e().uv(13, 1, 15, 4).noCull() : provider.getModel(this.texture).uvLock()
			.add(0, 5, 7, 2, 16, 9)
				.d().uv(0, 7, 2, 9).noCull()
				.u().uv(0, 7, 2, 9).noCull()
				.n().uv(0, 0, 2, 11).noCull()
				.s().uv(0, 0, 2, 11).noCull()
				.w().uv(7, 0, 9, 11)
				.e().uv(7, 0, 9, 11).noCull()
			.add(14, 5, 7, 16, 16, 9)
				.d().uv(14, 7, 16, 9).noCull()
				.u().uv(14, 7, 16, 9).noCull()
				.n().uv(14, 0, 16, 11).noCull()
				.s().uv(14, 0, 16, 11).noCull()
				.w().uv(7, 0, 9, 11).noCull()
				.e().uv(7, 0, 9, 11)
			.add(6, 6, 7, 8, 15, 9)
				.d().uv(6, 7, 8, 9).noCull()
				.u().uv(6, 7, 8, 9).noCull()
				.n().uv(6, 1, 8, 10).noCull()
				.s().uv(6, 1, 8, 10).noCull()
				.w().uv(7, 1, 9, 10).noCull()
				.e().uv(7, 1, 9, 10).noCull()
			.add(8, 6, 7, 10, 15, 9)
				.d().uv(8, 7, 10, 9).noCull()
				.u().uv(8, 7, 10, 9).noCull()
				.n().uv(8, 1, 10, 10).noCull()
				.s().uv(8, 1, 10, 10).noCull()
				.w().uv(7, 1, 9, 10).noCull()
				.e().uv(7, 1, 9, 10).noCull()
			.add(2, 6, 7, 6, 9, 9)
				.d().uv(2, 7, 6, 9).noCull()
				.u().uv(2, 7, 6, 9).noCull()
				.n().uv(2, 7, 6, 10).noCull()
				.s().uv(2, 7, 6, 10).noCull()
			.add(2, 12, 7, 6, 15, 9)
				.d().uv(2, 7, 6, 9).noCull()
				.u().uv(2, 7, 6, 9).noCull()
				.n().uv(2, 1, 6, 4).noCull()
				.s().uv(2, 1, 6, 4).noCull()
			.add(10, 6, 7, 14, 9, 9)
				.d().uv(10, 7, 14, 9).noCull()
				.u().uv(10, 7, 14, 9).noCull()
				.n().uv(10, 7, 14, 10).noCull()
				.s().uv(10, 7, 14, 10).noCull()
			.add(10, 12, 7, 14, 15, 9)
				.d().uv(10, 7, 14, 9).noCull()
				.u().uv(10, 7, 14, 9).noCull()
				.n().uv(10, 1, 14, 4).noCull()
				.s().uv(10, 1, 14, 4).noCull()))
    			.rotate(ModelRotation.getNorthRot(state.getValue(FACING).getOpposite()));
    }

    public Property<?>[] getIgnoredProperties() {
    	return new Property[] {POWERED};
    }
}
