package common.block;

import java.util.List;

import common.collect.Lists;
import common.entity.Entity;
import common.entity.types.EntityLiving;
import common.item.CheatTab;
import common.item.Item;
import common.item.ItemStack;
import common.material.Material;
import common.model.Model;
import common.model.ModelProvider;
import common.properties.IProperty;
import common.properties.PropertyBool;
import common.properties.PropertyDirection;
import common.util.BlockPos;
import common.util.BoundingBox;
import common.util.Facing;
import common.util.Facing.Axis;
import common.world.IWorldAccess;
import common.world.State;
import common.world.World;

public class BlockSlab extends Block
{
    public static final PropertyDirection FACING = PropertyDirection.create("facing");
    public static final PropertyBool DOUBLE = PropertyBool.create("double");
    public static final PropertyBool SEAMLESS = PropertyBool.create("seamless");
    public static final List<BlockSlab> SLABS = Lists.newArrayList();
    
    private final String textureTop;
    private final String textureBottom;
    private final String textureSide;
    
    public BlockSlab(Material materialIn, String texture)
    {
    	this(materialIn, texture, texture, texture);
    }
    
    public BlockSlab(Material materialIn, String side, String bottom, String top)
    {
        super(materialIn);
        this.setDefaultState(this.getBaseState().withProperty(FACING, Facing.DOWN).withProperty(DOUBLE, false)
        		.withProperty(SEAMLESS, false));
        this.setTab(materialIn == Material.wood ? CheatTab.tabWood : CheatTab.tabBlocks);

//        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.5F);
        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);

        this.setLightOpacity(255);
        this.textureTop = top;
        this.textureBottom = bottom;
        this.textureSide = side;
        SLABS.add(this);
    }
    
    public State getStateFromMeta(int meta)
    {
    	meta = meta & 7;
        return this.getState().withProperty(DOUBLE, meta >= 6).withProperty(SEAMLESS, meta == 7)
        		.withProperty(FACING, (meta == 0 || meta >= 6) ? Facing.DOWN : 
        		(meta == 1 ? Facing.UP : Facing.getHorizontal(meta - 2)));
    }
    
    public int getMetaFromState(State state)
    {
    	if(state.getValue(DOUBLE))
    		return state.getValue(SEAMLESS) ? 7 : 6;
        Facing dir = state.getValue(FACING);
        return dir == Facing.DOWN ? 0 : (dir == Facing.UP ? 1 : (dir.getHorizontalIndex() + 2));
    }

    protected IProperty[] getProperties()
    {
        return new IProperty[] {FACING, DOUBLE, SEAMLESS};
    }

    public boolean canSilkHarvest()
    {
        return false;
    }
    
    public void dropBlockAsItemWithChance(World worldIn, BlockPos pos, State state, float chance, int fortune)
    {
        if (!worldIn.client)
        {
            int i = state.getBlock() == this && state.getValue(DOUBLE) ? 2 : 1;

            for (int j = 0; j < i; ++j)
            {
                if (worldIn.rand.floatv() <= chance)
                {
                    Item item = this.getItemDropped(state, worldIn.rand, fortune);

                    if (item != null)
                    {
                        spawnAsEntity(worldIn, pos, new ItemStack(item, 1, this.damageDropped(state)));
                    }
                }
            }
        }
    }
    
    public State onBlockPlaced(World worldIn, BlockPos pos, Facing facing, float hitX, float hitY, float hitZ, int meta, EntityLiving placer)
    {
        State iblockstate = this.getState().withProperty(FACING, Facing.DOWN);
        return facing != Facing.DOWN && (facing == Facing.UP || (double)hitY <= 0.5D) ? iblockstate : 
        		iblockstate.withProperty(FACING, Facing.UP);
    }
    
    public void setBlockBoundsBasedOnState(IWorldAccess worldIn, BlockPos pos)
    {
//        if (this.isDouble())
//        {
//            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
//        }
//        else
//        {
        State iblockstate = worldIn.getState(pos);

        if (iblockstate.getBlock() == this)
        {
        	if(iblockstate.getValue(DOUBLE)) {
        		this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
        		return;
        	}
        	switch(iblockstate.getValue(FACING)) {
        	case EAST:
                this.setBlockBounds(0.5F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
        		break;
        	case WEST:
                this.setBlockBounds(0.0F, 0.0F, 0.0F, 0.5F, 1.0F, 1.0F);
        		break;
        	case SOUTH:
                this.setBlockBounds(0.0F, 0.0F, 0.5F, 1.0F, 1.0F, 1.0F);
        		break;
        	case NORTH:
                this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.5F);
        		break;
        	case UP:
        		this.setBlockBounds(0.0F, 0.5F, 0.0F, 1.0F, 1.0F, 1.0F);
        		break;
        	case DOWN:
        		this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
        		break;
        	}
        	
//            if (iblockstate.getValue(HALF) == BlockSlab.EnumBlockHalf.TOP)
//            {
//                
//            }
//            else
//            {
//                
//            }
        }
//        }
    }

//    public void setBlockBoundsBasedOnState(IWorldAccess worldIn, BlockPos pos)
//    {
//        IBlockState iblockstate = worldIn.getBlockState(pos);
//
//        if (iblockstate.getBlock() == this)
//        {
//        }
//    }
    
    public void setBlockBoundsForItemRender()
    {
//    	this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.5F);
    	this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
    }
    
    public void addCollisionBoxesToList(World worldIn, BlockPos pos, State state, BoundingBox mask, List<BoundingBox> list, Entity collidingEntity)
    {
        this.setBlockBoundsBasedOnState(worldIn, pos);
        super.addCollisionBoxesToList(worldIn, pos, state, mask, list, collidingEntity);
    }
    
    public boolean isOpaqueCube()
    {
        return false;
    }
    
//    public IBlockState onBlockPlaced(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
//    {
//    	return super.onBlockPlaced(worldIn, pos, facing, hitX, hitY, hitZ, meta, placer).withProperty(FACING, placer.getHorizontalFacing() /* .getOpposite() */);
//    }

    public boolean isFullCube()
    {
        return false;
    }

    protected static boolean isSlab(Block blockIn)
    {
        return blockIn instanceof BlockSlab;
    }

    public boolean shouldSideBeRendered(IWorldAccess worldIn, BlockPos pos, Facing side)
    {
        State iblockstate = worldIn.getState(pos);
        if (iblockstate.getBlock() == this && iblockstate.getValue(DOUBLE))
        {
            return super.shouldSideBeRendered(worldIn, pos, side);
        }
        if(iblockstate.getBlock() == this && iblockstate.getValue(FACING).getAxis() == Axis.Y) {
        	if (side != Facing.UP && side != Facing.DOWN && !super.shouldSideBeRendered(worldIn, pos, side))
            {
                return false;
            }
            else
            {
                BlockPos blockpos = pos.offset(side.getOpposite());
//                IBlockState iblockstate = worldIn.getBlockState(pos);
                State iblockstate1 = worldIn.getState(blockpos);
            	if(isSlab(iblockstate1.getBlock()) && iblockstate.getValue(FACING).getAxis() == Axis.Y)
            		return true;
                boolean flag = isSlab(iblockstate.getBlock()) && iblockstate.getValue(FACING) == Facing.UP;
                boolean flag1 = isSlab(iblockstate1.getBlock()) && iblockstate1.getValue(FACING) == Facing.UP;
                return flag1 ? (side == Facing.DOWN ? true : (side == Facing.UP && super.shouldSideBeRendered(worldIn, pos, side) ? true : !isSlab(iblockstate.getBlock()) || !flag)) : (side == Facing.UP ? true : (side == Facing.DOWN && super.shouldSideBeRendered(worldIn, pos, side) ? true : !isSlab(iblockstate.getBlock()) || flag));
            }
        }
        
        if (side == Facing.UP || side == Facing.DOWN)
        {
            return super.shouldSideBeRendered(worldIn, pos, side);
        }
        else
        {
            return (iblockstate.getBlock() == this && iblockstate.getValue(FACING) == side.getOpposite()) || super.shouldSideBeRendered(worldIn, pos, side);
        }
    }

//    public boolean shouldSideBeRendered(IWorldAccess worldIn, BlockPos pos, EnumFacing side)
//    {
//        
//        
//    }
    
//    public abstract String getUnlocalizedName(int meta);
    
//    public int getDamageValue(World worldIn, BlockPos pos)
//    {
//        return super.getDamageValue(worldIn, pos) & 7;
//    }

//    public abstract IProperty<?> getVariantProperty();
//
//    public abstract Object getVariant(ItemStack stack);
    
    public Model getModel(ModelProvider provider, String name, State state) {
    	if(state.getValue(DOUBLE)) {
    		return provider.getModel(state.getValue(SEAMLESS) ? this.textureTop : this.textureSide)
    				.add().nswe().d(state.getValue(SEAMLESS) ? this.textureTop : this.textureBottom).u(this.textureTop);
    	}
    	else {
	    	if(state.getValue(FACING).getAxis() != Axis.Y)
	    		return provider.getModel(this.textureSide).vslab(state.getValue(FACING), this.textureBottom, this.textureTop);
	    	else
	    		return provider.getModel(this.textureSide).slab(state.getValue(FACING) == Facing.UP, this.textureBottom,
	    		this.textureTop);
    	}
    }
    
    /*
    public Model getModel(String name, IBlockState state) {
    	if(state.getValue(VARIANT) == EnumType.STONE)
    		return state.getValue(SEAMLESS) ? provider.getModel("double_stone_top").add().all() : 
    				provider.getModel("stone_slab_side").add().nswe().du("double_stone_top");
    	else if(state.getValue(VARIANT) == EnumType.QUARTZ)
    		return provider.getModel("quartz_block_side").add().nswe().d("quartz_block_bottom").u("quartz_top");
    	else if(state.getValue(VARIANT) == EnumType.SAND)
    		return provider.getModel("sandstone_normal").add().nswe().d("sandstone_bottom").u("sandstone_all");
    	else
    		return provider.getModel(getTexture(state.getValue(VARIANT))).add().all();
    }
    
    public Model getModel(String name, IBlockState state) {
    	if(state.getValue(VARIANT) == EnumType.STONE)
    		return provider.getModel("stone_slab_side").slab(state.getValue(HALF) == EnumBlockHalf.TOP, "double_stone_top");
    	else if(state.getValue(VARIANT) == EnumType.QUARTZ)
    		return provider.getModel("quartz_block_side").slab(state.getValue(HALF) == EnumBlockHalf.TOP, "quartz_block_bottom",
    		"quartz_top");
    	else if(state.getValue(VARIANT) == EnumType.SAND)
    		return provider.getModel("sandstone_normal").slab(state.getValue(HALF) == EnumBlockHalf.TOP, "sandstone_bottom",
    		"sandstone_all");
    	else
    		return provider.getModel(getTexture(state.getValue(VARIANT))).slab(state.getValue(HALF) == EnumBlockHalf.TOP);
    }
    
    public Model getModel(String name, IBlockState state) {
    	return provider.getModel(state.getValue(VARIANT).getName() + "_planks").slab(state.getValue(HALF) == EnumBlockHalf.TOP);
    }
    
    public Model getModel(String name, IBlockState state) {
    	return provider.getModel(state.getValue(VARIANT).getName() + "_planks").add().all();
    }
    
    protected static String getTexture(BlockStoneSlab.EnumType type) {
    	switch(type) {
	    	case BRICK:
	    		return "brick_block";
	    	case SMOOTHBRICK:
	    		return "stonebrick_default";
	    	case WOOD:
	    		return "oak_planks";
			default:
				return type.getName();
    	}
    }
    
    private static String getTexture(BlockVertStoneSlab.EnumType type) {
    	switch(type) {
	    	case WOOD:
	    		return "oak_planks";
			default:
				return type.getName();
    	}
    }
    
    public Model getModel(String name, IBlockState state) {
    	if(state.getValue(VARIANT) == EnumType.STONE)
    		return provider.getModel("stone_slab_side").vslab(state.getValue(FACING), "double_stone_top");
    	else if(state.getValue(VARIANT) == EnumType.SAND)
    		return provider.getModel("sandstone_normal").vslab(state.getValue(FACING), "sandstone_bottom",
    		"sandstone_all");
    	else
    		return provider.getModel(getTexture(state.getValue(VARIANT))).vslab(state.getValue(FACING));
    }
    
    private static String getTexture(BlockVertStoneSlab2.EnumType type) {
    	switch(type) {
	    	case BRICK:
	    		return "brick_block";
	    	case SMOOTHBRICK:
	    		return "stonebrick_default";
			default:
				return type.getName();
    	}
    }
    
    public Model getModel(String name, IBlockState state) {
    	if(state.getValue(VARIANT) == EnumType.QUARTZ)
    		return provider.getModel("quartz_block_side").vslab(state.getValue(FACING), "quartz_block_bottom",
    		"quartz_top");
    	else
    		return provider.getModel(getTexture(state.getValue(VARIANT))).vslab(state.getValue(FACING));
    }
    
    public Model getModel(String name, IBlockState state) {
    	return provider.getModel(state.getValue(VARIANT).getName() + "_planks").vslab(state.getValue(FACING));
    }
    
    public Model getModel(String name, IBlockState state) {
    	return provider.getModel(state.getValue(VARIANT).getName() + "_planks").vslab(state.getValue(FACING));
    }
    */
}
