package common.block.tech;

import java.util.List;

import common.block.Block;
import common.block.Directional;
import common.block.Material;
import common.block.SoundType;
import common.entity.Entity;
import common.init.Blocks;
import common.init.Items;
import common.item.Item;
import common.model.Model;
import common.model.ModelProvider;
import common.model.ModelRotation;
import common.properties.Property;
import common.properties.PropertyBool;
import common.properties.PropertyEnum;
import common.rng.Random;
import common.util.BlockPos;
import common.util.BoundingBox;
import common.util.Facing;
import common.util.Identifyable;
import common.world.IWorldAccess;
import common.world.State;
import common.world.World;
import common.world.AWorldServer;

public class BlockPistonHead extends Block implements Directional
{
    public static final PropertyEnum<BlockPistonHead.EnumPistonType> TYPE = PropertyEnum.<BlockPistonHead.EnumPistonType>create("type", BlockPistonHead.EnumPistonType.class);
    public static final PropertyBool SHORT = PropertyBool.create("short");

    public BlockPistonHead()
    {
        super(Material.PISTON);
        this.setDefaultState(this.getBaseState().withProperty(FACING, Facing.NORTH).withProperty(TYPE, BlockPistonHead.EnumPistonType.DEFAULT).withProperty(SHORT, Boolean.valueOf(false)));
        this.setStepSound(SoundType.STONE);
        this.setHardness(0.5F);
    }

//    public void onBlockHarvested(World worldIn, BlockPos pos, State state, EntityNPC player)
//    {
//        if (player.creative)
//        {
//            Facing enumfacing = (Facing)state.getValue(FACING);
//
//            if (enumfacing != null)
//            {
//                BlockPos blockpos = pos.offset(enumfacing.getOpposite());
//                Block block = worldIn.getState(blockpos).getBlock();
//
//                if (block == Blocks.piston || block == Blocks.sticky_piston)
//                {
//                    worldIn.setBlockToAir(blockpos);
//                }
//            }
//        }
//
//        super.onBlockHarvested(worldIn, pos, state, player);
//    }

    public void onBlockRemoved(AWorldServer worldIn, BlockPos pos, State state)
    {
        super.onBlockRemoved(worldIn, pos, state);
        Facing enumfacing = ((Facing)state.getValue(FACING)).getOpposite();
        pos = pos.offset(enumfacing);
        State iblockstate = worldIn.getState(pos);

        if ((iblockstate.getBlock() == Blocks.piston || iblockstate.getBlock() == Blocks.sticky_piston) && ((Boolean)iblockstate.getValue(BlockPistonBase.EXTENDED)).booleanValue())
        {
            iblockstate.getBlock().dropBlockAsItem(worldIn, pos, iblockstate, 0);
            worldIn.setBlockToAir(pos);
        }
    }

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

    public boolean isFullCube()
    {
        return false;
    }

    public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
    {
        return false;
    }

    /**
     * Check whether this Block can be placed on the given side
     */
    public boolean canPlaceBlockOnSide(World worldIn, BlockPos pos, Facing side)
    {
        return false;
    }

    /**
     * Returns the quantity of items to drop on block destruction.
     */
    public int quantityDropped(Random random)
    {
        return 0;
    }

    /**
     * Add all collision boxes of this Block to the list that intersect with the given mask.
     */
    public void addCollisionBoxesToList(World worldIn, BlockPos pos, State state, BoundingBox mask, List<BoundingBox> list, Entity collidingEntity)
    {
        this.applyHeadBounds(state);
        super.addCollisionBoxesToList(worldIn, pos, state, mask, list, collidingEntity);
        this.applyCoreBounds(state);
        super.addCollisionBoxesToList(worldIn, pos, state, mask, list, collidingEntity);
        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
    }

    private void applyCoreBounds(State state)
    {
        float f = 0.25F;
        float f1 = 0.375F;
        float f2 = 0.625F;
        float f3 = 0.25F;
        float f4 = 0.75F;

        switch ((Facing)state.getValue(FACING))
        {
            case DOWN:
                this.setBlockBounds(0.375F, 0.25F, 0.375F, 0.625F, 1.0F, 0.625F);
                break;

            case UP:
                this.setBlockBounds(0.375F, 0.0F, 0.375F, 0.625F, 0.75F, 0.625F);
                break;

            case NORTH:
                this.setBlockBounds(0.25F, 0.375F, 0.25F, 0.75F, 0.625F, 1.0F);
                break;

            case SOUTH:
                this.setBlockBounds(0.25F, 0.375F, 0.0F, 0.75F, 0.625F, 0.75F);
                break;

            case WEST:
                this.setBlockBounds(0.375F, 0.25F, 0.25F, 0.625F, 0.75F, 1.0F);
                break;

            case EAST:
                this.setBlockBounds(0.0F, 0.375F, 0.25F, 0.75F, 0.625F, 0.75F);
        }
    }

    public void setBlockBoundsBasedOnState(IWorldAccess worldIn, BlockPos pos)
    {
        this.applyHeadBounds(worldIn.getState(pos));
    }

    public void applyHeadBounds(State state)
    {
        float f = 0.25F;
        Facing enumfacing = (Facing)state.getValue(FACING);

        if (enumfacing != null)
        {
            switch (enumfacing)
            {
                case DOWN:
                    this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.25F, 1.0F);
                    break;

                case UP:
                    this.setBlockBounds(0.0F, 0.75F, 0.0F, 1.0F, 1.0F, 1.0F);
                    break;

                case NORTH:
                    this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.25F);
                    break;

                case SOUTH:
                    this.setBlockBounds(0.0F, 0.0F, 0.75F, 1.0F, 1.0F, 1.0F);
                    break;

                case WEST:
                    this.setBlockBounds(0.0F, 0.0F, 0.0F, 0.25F, 1.0F, 1.0F);
                    break;

                case EAST:
                    this.setBlockBounds(0.75F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
            }
        }
    }

    /**
     * Called when a neighboring block changes.
     */
    public void onNeighborBlockChange(World worldIn, BlockPos pos, State state, Block neighborBlock)
    {
        Facing enumfacing = (Facing)state.getValue(FACING);
        BlockPos blockpos = pos.offset(enumfacing.getOpposite());
        State iblockstate = worldIn.getState(blockpos);

        if (iblockstate.getBlock() != Blocks.piston && iblockstate.getBlock() != Blocks.sticky_piston)
        {
            worldIn.setBlockToAir(pos);
        }
        else
        {
            iblockstate.getBlock().onNeighborBlockChange(worldIn, blockpos, iblockstate, neighborBlock);
        }
    }

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

    public static Facing getFacing(int meta)
    {
        int i = meta & 7;
        return i > 5 ? Facing.getFront(0) : Facing.getFront(i);
    }

    public Item getItem(World worldIn, BlockPos pos)
    {
        return worldIn.getState(pos).getValue(TYPE) == BlockPistonHead.EnumPistonType.STICKY ? Items.sticky_piston : Items.piston;
    }

    /**
     * Convert the given metadata into a BlockState for this Block
     */
    public State getStateFromMeta(int meta)
    {
        return this.getState().withProperty(FACING, getFacing(meta)).withProperty(TYPE, (meta & 8) > 0 ? BlockPistonHead.EnumPistonType.STICKY : BlockPistonHead.EnumPistonType.DEFAULT);
    }

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

        if (state.getValue(TYPE) == BlockPistonHead.EnumPistonType.STICKY)
        {
            i |= 8;
        }

        return i;
    }

    protected Property[] getProperties()
    {
        return new Property[] {FACING, TYPE, SHORT};
    }

    public Model getModel(ModelProvider provider, String name, State state) {
    	String side = "piston_side";
    	return (state.getValue(SHORT) ? provider.getModel(state.getValue(TYPE) == EnumPistonType.STICKY ? "piston_top_sticky" : "piston_top")
			.add(0, 0, 0, 16, 16, 4)
				.d(side).uv(0, 0, 16, 4).rot(180)
				.u(side).uv(0, 0, 16, 4)
				.n().uv(0, 0, 16, 16)
				.s("piston_top").uv(0, 0, 16, 16).noCull()
				.w(side).uv(0, 0, 16, 4).rot(270)
				.e(side).uv(0, 0, 16, 4).rot(90)
			.add(6, 6, 4, 10, 10, 16)
				.d(side).uv(4, 0, 16, 4).rot(90).noCull()
				.u(side).uv(4, 0, 16, 4).rot(270).noCull()
				.w(side).uv(16, 4, 4, 0).noCull()
				.e(side).uv(4, 0, 16, 4).noCull() 
				: provider.getModel(state.getValue(TYPE) == EnumPistonType.STICKY ? "piston_top_sticky" : "piston_top")
			.add(0, 0, 0, 16, 16, 4)
				.d(side).uv(0, 0, 16, 4).rot(180)
				.u(side).uv(0, 0, 16, 4)
				.n().uv(0, 0, 16, 16)
				.s("piston_top").uv(0, 0, 16, 16).noCull()
				.w(side).uv(0, 0, 16, 4).rot(270)
				.e(side).uv(0, 0, 16, 4).rot(90)
			.add(6, 6, 4, 10, 10, 16)
				.d(side).uv(4, 0, 16, 4).rot(90).noCull()
				.u(side).uv(4, 0, 16, 4).rot(270).noCull()
				.w(side).uv(16, 4, 4, 0).noCull()
				.e(side).uv(4, 0, 16, 4).noCull()
			.add(6, 6, 16, 10, 10, 20)
				.d(side).uv(0, 0, 4, 4).rot(90).noCull()
				.u(side).uv(0, 0, 4, 4).rot(270).noCull()
				.w(side).uv(4, 4, 0, 0).noCull()
				.e(side).uv(0, 0, 4, 4).noCull())
    			.rotate(ModelRotation.getNorthRot(state.getValue(FACING).getAxis() == Facing.Axis.Y 
					? state.getValue(FACING).getOpposite() : state.getValue(FACING)));
    }
	
	protected Item getItemToRegister() {
		return null;
	}

    public static enum EnumPistonType implements Identifyable
    {
        DEFAULT("normal"),
        STICKY("sticky");

        private final String VARIANT;

        private EnumPistonType(String name)
        {
            this.VARIANT = name;
        }

        public String toString()
        {
            return this.VARIANT;
        }

        public String getName()
        {
            return this.VARIANT;
        }
    }
}
