package common.block.artificial;

import java.util.List;

import common.block.Block;
import common.block.Material;
import common.entity.Entity;
import common.init.Blocks;
import common.item.CheatTab;
import common.item.Item;
import common.item.block.ItemBlock;
import common.model.BlockLayer;
import common.model.Model;
import common.model.ModelProvider;
import common.model.ModelRotation;
import common.properties.Property;
import common.properties.PropertyBool;
import common.rng.Random;
import common.util.BlockPos;
import common.util.BoundingBox;
import common.util.Facing;
import common.world.IWorldAccess;
import common.world.State;
import common.world.World;

public class BlockPane extends Block
{
    public static final PropertyBool NORTH = PropertyBool.create("north");
    public static final PropertyBool EAST = PropertyBool.create("east");
    public static final PropertyBool SOUTH = PropertyBool.create("south");
    public static final PropertyBool WEST = PropertyBool.create("west");
    private final boolean canDrop;

    public BlockPane(Material materialIn, boolean canDrop)
    {
        super(materialIn);
        this.setDefaultState(this.getBaseState().withProperty(NORTH, Boolean.valueOf(false)).withProperty(EAST, Boolean.valueOf(false)).withProperty(SOUTH, Boolean.valueOf(false)).withProperty(WEST, Boolean.valueOf(false)));
        this.canDrop = canDrop;
        this.setTab(CheatTab.BLOCKS);
        this.setFlatItemTexture();
    }

    /**
     * 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)
    {
        return state.withProperty(NORTH, Boolean.valueOf(this.canPaneConnectToBlock(worldIn.getState(pos.north()).getBlock()))).withProperty(SOUTH, Boolean.valueOf(this.canPaneConnectToBlock(worldIn.getState(pos.south()).getBlock()))).withProperty(WEST, Boolean.valueOf(this.canPaneConnectToBlock(worldIn.getState(pos.west()).getBlock()))).withProperty(EAST, Boolean.valueOf(this.canPaneConnectToBlock(worldIn.getState(pos.east()).getBlock())));
    }

    /**
     * Get the Item that this Block should drop when harvested.
     */
    public Item getItemDropped(State state, Random rand, int fortune)
    {
        return !this.canDrop ? null : super.getItemDropped(state, rand, fortune);
    }

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

    public boolean isFullCube()
    {
        return false;
    }

    public boolean shouldSideBeRendered(IWorldAccess worldIn, BlockPos pos, Facing side)
    {
        return worldIn.getState(pos).getBlock() == this ? false : super.shouldSideBeRendered(worldIn, pos, side);
    }

    /**
     * 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)
    {
        boolean flag = this.canPaneConnectToBlock(worldIn.getState(pos.north()).getBlock());
        boolean flag1 = this.canPaneConnectToBlock(worldIn.getState(pos.south()).getBlock());
        boolean flag2 = this.canPaneConnectToBlock(worldIn.getState(pos.west()).getBlock());
        boolean flag3 = this.canPaneConnectToBlock(worldIn.getState(pos.east()).getBlock());

        if ((!flag2 || !flag3) && (flag2 || flag3 || flag || flag1))
        {
            if (flag2)
            {
                this.setBlockBounds(0.0F, 0.0F, 0.4375F, 0.5F, 1.0F, 0.5625F);
                super.addCollisionBoxesToList(worldIn, pos, state, mask, list, collidingEntity);
            }
            else if (flag3)
            {
                this.setBlockBounds(0.5F, 0.0F, 0.4375F, 1.0F, 1.0F, 0.5625F);
                super.addCollisionBoxesToList(worldIn, pos, state, mask, list, collidingEntity);
            }
        }
        else
        {
            this.setBlockBounds(0.0F, 0.0F, 0.4375F, 1.0F, 1.0F, 0.5625F);
            super.addCollisionBoxesToList(worldIn, pos, state, mask, list, collidingEntity);
        }

        if ((!flag || !flag1) && (flag2 || flag3 || flag || flag1))
        {
            if (flag)
            {
                this.setBlockBounds(0.4375F, 0.0F, 0.0F, 0.5625F, 1.0F, 0.5F);
                super.addCollisionBoxesToList(worldIn, pos, state, mask, list, collidingEntity);
            }
            else if (flag1)
            {
                this.setBlockBounds(0.4375F, 0.0F, 0.5F, 0.5625F, 1.0F, 1.0F);
                super.addCollisionBoxesToList(worldIn, pos, state, mask, list, collidingEntity);
            }
        }
        else
        {
            this.setBlockBounds(0.4375F, 0.0F, 0.0F, 0.5625F, 1.0F, 1.0F);
            super.addCollisionBoxesToList(worldIn, pos, state, mask, list, collidingEntity);
        }
    }

    /**
     * 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);
    }

    public void setBlockBoundsBasedOnState(IWorldAccess worldIn, BlockPos pos)
    {
        float f = 0.4375F;
        float f1 = 0.5625F;
        float f2 = 0.4375F;
        float f3 = 0.5625F;
        boolean flag = this.canPaneConnectToBlock(worldIn.getState(pos.north()).getBlock());
        boolean flag1 = this.canPaneConnectToBlock(worldIn.getState(pos.south()).getBlock());
        boolean flag2 = this.canPaneConnectToBlock(worldIn.getState(pos.west()).getBlock());
        boolean flag3 = this.canPaneConnectToBlock(worldIn.getState(pos.east()).getBlock());

        if ((!flag2 || !flag3) && (flag2 || flag3 || flag || flag1))
        {
            if (flag2)
            {
                f = 0.0F;
            }
            else if (flag3)
            {
                f1 = 1.0F;
            }
        }
        else
        {
            f = 0.0F;
            f1 = 1.0F;
        }

        if ((!flag || !flag1) && (flag2 || flag3 || flag || flag1))
        {
            if (flag)
            {
                f2 = 0.0F;
            }
            else if (flag1)
            {
                f3 = 1.0F;
            }
        }
        else
        {
            f2 = 0.0F;
            f3 = 1.0F;
        }

        this.setBlockBounds(f, 0.0F, f2, f1, 1.0F, f3);
    }

    public final boolean canPaneConnectToBlock(Block blockIn)
    {
        return blockIn.isFullBlock() || blockIn == this || blockIn == Blocks.glass || blockIn instanceof BlockStainedGlass || blockIn instanceof BlockStainedGlassPane || blockIn instanceof BlockPane;
    }

    public boolean canSilkHarvest()
    {
        return true;
    }

    public BlockLayer getBlockLayer()
    {
        return BlockLayer.CUTOUT_MIPPED;
    }

    /**
     * Convert the BlockState into the correct metadata value
     */
    public int getMetaFromState(State state)
    {
        return 0;
    }

    protected Property[] getProperties()
    {
        return new Property[] {NORTH, EAST, WEST, SOUTH};
    }
    
    public boolean isMagnetic() {
    	return this.material == Material.SOLID;
    }
	
	public boolean onShot(World world, BlockPos pos, State state, Entity projectile) {
		if(this.material != Material.SOLID)
			world.destroyBlock(pos, true);
		return this.material == Material.SOLID;
	}
    
    protected String getPaneBase(State state) {
    	return "glass";
    }
    
    protected String getPaneEdge(State state) {
    	return "glass_pane";
    }

    public Model getModel(ModelProvider provider, String name, State state) {
    	boolean n = state.getValue(NORTH);
    	boolean s = state.getValue(SOUTH);
    	boolean w = state.getValue(WEST);
    	boolean e = state.getValue(EAST);
    	int sides = (n ? 1 : 0) + (s ? 1 : 0) + (w ? 1 : 0) + (e ? 1 : 0);
    	if(this.canDrop) {
    		if(sides == 0 || sides == 4)
    			return provider.getModel(name)
				.add(8, 0, 0, 8, 16, 16)
					.w().uv(0, 0, 16, 16).noCull()
					.e().uv(0, 0, 16, 16).noCull()
				.add(7, 0, 0, 9, 16, 16)
					.n().uv(7, 0, 9, 16)
					.s().uv(7, 0, 9, 16)
				.add(7, 0.005f, 0, 9, 15.995f, 16)
					.d().uv(7, 0, 9, 16).noCull()
					.u().uv(9, 0, 7, 16).noCull()
				.add(0, 0, 8, 16, 16, 8)
					.n().uv(0, 0, 16, 16).noCull()
					.s().uv(0, 0, 16, 16).noCull()
				.add(0, 0, 7, 16, 16, 9)
					.w().uv(7, 0, 9, 16)
					.e().uv(7, 0, 9, 16)
				.add(0, 0.005f, 7, 7, 15.995f, 9)
					.d().uv(9, 9, 7, 16).rot(90).noCull()
					.u().uv(7, 9, 9, 16).rot(90).noCull()
				.add(9, 0.005f, 7, 16, 15.995f, 9)
					.d().uv(9, 0, 7, 7).rot(90).noCull()
					.u().uv(7, 0, 9, 7).rot(90).noCull();
    		else if(sides == 1)
    			return provider.getModel(name)
    			.add(8, 0, 0, 8, 16, 8)
    				.w().uv(8, 0, 16, 16).noCull()
    				.e().uv(8, 0, 16, 16).noCull()
    			.add(7, 0, 0, 9, 16, 9)
    				.n().uv(7, 0, 9, 16)
    				.s().uv(7, 0, 9, 16).noCull()
    			.add(7, 0.005f, 0, 9, 15.995f, 9)
    				.d().uv(9, 0, 7, 9).noCull()
    				.u().uv(7, 0, 9, 9).noCull()
    			.rotate(n ? ModelRotation.X0_Y0 : (s ? ModelRotation.X0_Y180 : (w ? ModelRotation.X0_Y270 : ModelRotation.X0_Y90)));
    		else if(sides == 2 && ((e != w) || (n != s)))
    			return provider.getModel(name)
    			.add(8, 0, 0, 8, 16, 8)
    				.w().uv(0, 0, 8, 16).noCull()
    				.e().uv(8, 0, 16, 16).noCull()
    			.add(7, 0, 0, 9, 16, 0)
    				.n().uv(7, 0, 9, 16)
    			.add(7, 0.005f, 0, 9, 15.995f, 9)
    				.d().uv(9, 0, 7, 9).noCull()
    				.u().uv(7, 0, 9, 9).noCull()
    			.add(8, 0, 8, 16, 16, 8)
    				.n().uv(0, 0, 8, 16).noCull()
    				.s().uv(8, 0, 16, 16).noCull()
    			.add(0, 0, 7, 16, 16, 9)
    				.e().uv(7, 0, 9, 16)
    			.add(9, 0.005f, 7, 16, 15.995f, 9)
    				.d().uv(9, 0, 7, 7).rot(90).noCull()
    				.u().uv(7, 0, 9, 7).rot(90).noCull()
        		.rotate(n && e ? ModelRotation.X0_Y0 : (s && w ? ModelRotation.X0_Y180 : 
        			(n && w ? ModelRotation.X0_Y270 : ModelRotation.X0_Y90)));
    		else if(sides == 2)
    			return provider.getModel(name)
    			.add(8, 0, 0, 8, 16, 16)
    				.w().uv(0, 0, 16, 16).noCull()
    				.e().uv(0, 0, 16, 16).noCull()
    			.add(7, 0, 0, 9, 16, 16)
    				.n().uv(7, 0, 9, 16)
    				.s().uv(7, 0, 9, 16)
    			.add(7, 0.005f, 0, 9, 15.995f, 16)
    				.d().uv(7, 0, 9, 16).noCull()
    				.u().uv(9, 0, 7, 16).noCull()
        		.rotate(n ? ModelRotation.X0_Y0 : ModelRotation.X0_Y90);
    		else
    			return provider.getModel(name)
    			.add(8, 0, 0, 8, 16, 16)
    				.w().uv(0, 0, 16, 16).noCull()
    				.e().uv(0, 0, 16, 16).noCull()
    			.add(7, 0, 0, 9, 16, 16)
    				.n().uv(7, 0, 9, 16)
    				.s().uv(7, 0, 9, 16)
    			.add(7, 0.005f, 0, 9, 15.995f, 16)
    				.d().uv(7, 0, 9, 16).noCull()
    				.u().uv(9, 0, 7, 16).noCull()
    			.add(8, 0, 8, 16, 16, 8)
    				.n().uv(0, 0, 8, 16).noCull()
    				.s().uv(8, 0, 16, 16).noCull()
    			.add(0, 0, 7, 16, 16, 9)
    				.e().uv(7, 0, 9, 16)
    			.add(9, 0.005f, 7, 16, 15.995f, 9)
    				.d().uv(9, 0, 7, 7).rot(90).noCull()
    				.u().uv(7, 0, 9, 7).rot(90).noCull()
        		.rotate(!w ? ModelRotation.X0_Y0 : (!e ? ModelRotation.X0_Y180 : (!s ? ModelRotation.X0_Y270 : ModelRotation.X0_Y90)));
    	}
    	else {
    		String pane = this.getPaneBase(state);
    		String edge = this.getPaneEdge(state);
    		if(sides == 0 || sides == 4)
    			return provider.getModel(pane)
    					.add(7, 0, 0, 9, 16, 16).noShade()
    						.d(edge).uv(7, 0, 9, 16).noCull()
    						.u(edge).uv(7, 0, 9, 16).noCull()
    						.n(edge).uv(7, 0, 9, 16)
    						.s(edge).uv(7, 0, 9, 16)
    						.w().uv(0, 0, 16, 16).noCull()
    						.e().uv(0, 0, 16, 16).noCull()
    					.add(0, 0, 7, 16, 16, 9).noShade()
    						.d(edge).uv(7, 0, 9, 16).rot(90).noCull()
    						.u(edge).uv(7, 0, 9, 16).rot(90).noCull()
    						.n().uv(0, 0, 16, 16).noCull()
    						.s().uv(0, 0, 16, 16).noCull()
    						.w(edge).uv(7, 0, 9, 16)
    						.e(edge).uv(7, 0, 9, 16);
    		else if(sides == 1 && (n || e))
    			return provider.getModel(pane)
    				.add(7, 0, 0, 9, 16, 9).noShade()
    					.d(edge).uv(7, 0, 9, 9).noCull()
    					.u(edge).uv(7, 0, 9, 9).noCull()
    					.n(edge).uv(7, 0, 9, 16)
    					.s(edge).uv(7, 0, 9, 16).noCull()
    					.w().uv(16, 0, 7, 16).noCull()
    					.e().uv(7, 0, 16, 16).noCull()
    	        		.rotate(n ? ModelRotation.X0_Y0 : ModelRotation.X0_Y90);
    		else if(sides == 1)
    			return provider.getModel(pane)
					.add(7, 0, 7, 9, 16, 16).noShade()
						.d(edge).uv(7, 7, 9, 16).noCull()
						.u(edge).uv(7, 7, 9, 16).noCull()
						.n(edge).uv(7, 0, 9, 16)
						.s(edge).uv(7, 0, 9, 16).noCull()
						.w().uv(9, 0, 0, 16).noCull()
						.e().uv(0, 0, 9, 16).noCull()
    	        		.rotate(s ? ModelRotation.X0_Y0 : ModelRotation.X0_Y90);
    		else if(e && n && !s && !w)
    			return provider.getModel(pane)
    					.add(7, 0, 0, 9, 16, 9).noShade()
    						.d(edge).uv(7, 0, 9, 9).noCull()
    						.u(edge).uv(7, 0, 9, 9).noCull()
    						.n(edge).uv(7, 0, 9, 16)
    						.s(edge).uv(7, 0, 9, 16).noCull()
    						.w().uv(16, 0, 7, 16).noCull()
    						.e().uv(7, 0, 16, 16).noCull()
    					.add(9, 0, 7, 16, 16, 9).noShade()
    						.d(edge).uv(7, 9, 9, 16).rot(90).noCull()
    						.u(edge).uv(7, 9, 9, 16).rot(90).noCull()
    						.n().uv(16, 0, 9, 16).noCull()
    						.s().uv(9, 0, 16, 16).noCull()
    						.w().uv(7, 0, 9, 16).noCull()
    						.e(edge).uv(7, 0, 9, 16);
    		else if(e && !n && s && !w)
    			return provider.getModel(pane)
    					.add(7, 0, 7, 9, 16, 16).noShade()
    						.d(edge).uv(7, 7, 9, 16).noCull()
    						.u(edge).uv(7, 7, 9, 16).noCull()
    						.n(edge).uv(7, 0, 9, 16)
    						.s(edge).uv(7, 0, 9, 16).noCull()
    						.w().uv(9, 0, 0, 16).noCull()
    						.e().uv(0, 0, 9, 16).noCull()
    					.add(9, 0, 7, 16, 16, 9).noShade()
    						.d(edge).uv(7, 9, 9, 16).rot(90).noCull()
    						.u(edge).uv(7, 9, 9, 16).rot(90).noCull()
    						.n().uv(16, 0, 9, 16).noCull()
    						.s().uv(9, 0, 16, 16).noCull()
    						.w().uv(7, 0, 9, 16).noCull()
    						.e(edge).uv(7, 0, 9, 16);
    		else if(!e && !n && s && w)
    			return provider.getModel(pane)
    					.add(7, 0, 7, 9, 16, 16).noShade()
    						.d(edge).uv(7, 7, 9, 16).noCull()
    						.u(edge).uv(7, 7, 9, 16).noCull()
    						.n(edge).uv(7, 0, 9, 16)
    						.s(edge).uv(7, 0, 9, 16).noCull()
    						.w().uv(9, 0, 0, 16).noCull()
    						.e().uv(0, 0, 9, 16).noCull()
    					.add(0, 0, 7, 7, 16, 9).noShade()
    						.d(edge).uv(7, 0, 9, 7).rot(90).noCull()
    						.u(edge).uv(7, 0, 9, 7).rot(90).noCull()
    						.n().uv(7, 0, 0, 16).noCull()
    						.s().uv(0, 0, 7, 16).noCull()
    						.w(edge).uv(7, 0, 9, 16)
    						.e().uv(7, 0, 9, 16).noCull();
    		else if(!e && n && !s && w)
    			return provider.getModel(pane)
    					.add(7, 0, 0, 9, 16, 9).noShade()
    						.d(edge).uv(7, 0, 9, 9).noCull()
    						.u(edge).uv(7, 0, 9, 9).noCull()
    						.n(edge).uv(7, 0, 9, 16)
    						.s(edge).uv(7, 0, 9, 16).noCull()
    						.w().uv(16, 0, 7, 16).noCull()
    						.e().uv(7, 0, 16, 16).noCull()
    					.add(0, 0, 7, 7, 16, 9).noShade()
    						.d(edge).uv(7, 0, 9, 7).rot(90).noCull()
    						.u(edge).uv(7, 0, 9, 7).rot(90).noCull()
    						.n().uv(7, 0, 0, 16).noCull()
    						.s().uv(0, 0, 7, 16).noCull()
    						.w(edge).uv(7, 0, 9, 16)
    						.e().uv(7, 0, 9, 16).noCull();
        	else if((!e && n && s && !w) || (e && !n && !s && w))
        		return provider.getModel(pane)
    				.add(7, 0, 0, 9, 16, 16).noShade()
    					.d(edge).uv(7, 0, 9, 16).noCull()
    					.u(edge).uv(7, 0, 9, 16).noCull()
    					.n(edge).uv(7, 0, 9, 16).noCull()
    					.s(edge).uv(7, 0, 9, 16).noCull()
    					.w().uv(16, 0, 0, 16).noCull()
    					.e().uv(0, 0, 16, 16).noCull()
    					.rotate(s ? ModelRotation.X0_Y0 : ModelRotation.X0_Y90);
    		else if(!w)
    			return provider.getModel(pane)
    					.add(7, 0, 0, 9, 16, 16).noShade()
    						.d(edge).uv(7, 0, 9, 16).noCull()
    						.u(edge).uv(7, 0, 9, 16).noCull()
    						.n(edge).uv(7, 0, 9, 16)
    						.s(edge).uv(7, 0, 9, 16)
    						.w().uv(16, 0, 0, 16).noCull()
    						.e().uv(0, 0, 16, 16).noCull()
    					.add(9, 0, 7, 16, 16, 9).noShade()
    						.d(edge).uv(7, 9, 9, 16).rot(90).noCull()
    						.u(edge).uv(7, 9, 9, 16).rot(90).noCull()
    						.n().uv(16, 0, 9, 16).noCull()
    						.s().uv(9, 0, 16, 16).noCull()
    						.w(edge).uv(7, 0, 9, 16).noCull()
    						.e(edge).uv(7, 0, 9, 16);
        	else if(!n)
        		return provider.getModel(pane)
        				.add(7, 0, 9, 9, 16, 16).noShade()
        					.d(edge).uv(7, 9, 9, 16).noCull()
        					.u(edge).uv(7, 9, 9, 16).noCull()
        					.n(edge).uv(7, 0, 9, 16).noCull()
        					.s(edge).uv(7, 0, 9, 16)
        					.w().uv(7, 0, 0, 16).noCull()
        					.e().uv(0, 0, 7, 16).noCull()
        				.add(0, 0, 7, 16, 16, 9).noShade()
        					.d(edge).uv(7, 0, 9, 16).rot(90).noCull()
        					.u(edge).uv(7, 0, 9, 16).rot(90).noCull()
        					.n().uv(16, 0, 0, 16).noCull()
        					.s().uv(0, 0, 16, 16).noCull()
        					.w(edge).uv(7, 0, 9, 16)
        					.e(edge).uv(7, 0, 9, 16);
            else if(!e)
        		return provider.getModel(pane)
        				.add(7, 0, 0, 9, 16, 16).noShade()
        					.d(edge).uv(7, 0, 9, 16).noCull()
        					.u(edge).uv(7, 0, 9, 16).noCull()
        					.n(edge).uv(7, 0, 9, 16)
        					.s(edge).uv(7, 0, 9, 16)
        					.w().uv(16, 0, 0, 16).noCull()
        					.e().uv(0, 0, 16, 16).noCull()
        				.add(0, 0, 7, 7, 16, 9).noShade()
        					.d(edge).uv(7, 0, 9, 7).rot(90).noCull()
        					.u(edge).uv(7, 0, 9, 7).rot(90).noCull()
        					.n().uv(7, 0, 0, 16).noCull()
        					.s().uv(0, 0, 7, 16).noCull()
        					.w(edge).uv(7, 0, 9, 16).cull(Facing.EAST)
        					.e(edge).uv(7, 0, 9, 16).noCull();
            else
        		return provider.getModel(pane)
        				.add(7, 0, 0, 9, 16, 7).noShade()
        					.d(edge).uv(7, 0, 9, 7).noCull()
        					.u(edge).uv(7, 0, 9, 7).noCull()
        					.n(edge).uv(7, 0, 9, 16)
        					.s(edge).uv(7, 0, 9, 16).noCull()
        					.w().uv(16, 0, 9, 16).noCull()
        					.e().uv(9, 0, 16, 16).noCull()
        				.add(0, 0, 7, 16, 16, 9).noShade()
        					.d(edge).uv(7, 0, 9, 16).rot(90).noCull()
        					.u(edge).uv(7, 0, 9, 16).rot(90).noCull()
        					.n().uv(16, 0, 0, 16).noCull()
        					.s().uv(0, 0, 16, 16).noCull()
        					.w(edge).uv(7, 0, 9, 16)
        					.e(edge).uv(7, 0, 9, 16);
    	}
    }
	
	protected Item getItemToRegister() {
		return this.canDrop ? super.getItemToRegister() : new ItemBlock(this, "glass", false);
	}
}
