package common.block;

import java.util.Map;

import common.entity.Entity;
import common.init.Blocks;
import common.item.Item;
import common.material.Material;
import common.model.BlockLayer;
import common.model.Model;
import common.model.ModelProvider;
import common.model.ParticleType;
import common.properties.IProperty;
import common.properties.PropertyEnum;
import common.properties.PropertyInteger;
import common.rng.Random;
import common.util.BlockPos;
import common.util.BoundingBox;
import common.util.Facing;
import common.util.Facing.Axis;
import common.world.IWorldAccess;
import common.world.AWorldClient;
import common.world.State;
import common.world.World;

public class BlockPortal extends BlockBreakable
{
    public static final PropertyEnum<Facing.Axis> AXIS = PropertyEnum.<Facing.Axis>create("axis", Facing.Axis.class, Facing.Axis.X, Facing.Axis.Z);
    public static final PropertyInteger DIM = PropertyInteger.create("dim", 0, 7);
    
    private static final int[] COLORS = new int[] {0x000000, 0xff0000, 0xffff00, 0x00ff00, 0x00ffff, 0x0000ff, 0xff00ff, 0xffffff};

    public BlockPortal()
    {
        super(Material.portal, false);
        this.setDefaultState(this.getBaseState().withProperty(AXIS, Facing.Axis.X).withProperty(DIM, 0));
//        this.setTickRandomly();
    }

//    public void updateTick(IWorldServer worldIn, BlockPos pos, IBlockState state, Random rand)
//    {
////        super.updateTick(worldIn, pos, state, rand);
//
//        if (/* worldIn.isPrimary() && */ Config.mobSpawning && Config.pigmanPortalChance > 0 && rand.zrange(Config.pigmanPortalChance) < worldIn.getDifficulty().getId())
//        {
//            int i = pos.getY();
//            BlockPos blockpos;
//
//            for (blockpos = pos; !worldIn.isBlockSolid(blockpos) && blockpos.getY() > 0; blockpos = blockpos.down())
//            {
//                ;
//            }
//
//            if (i > 0 && !worldIn.getBlockState(blockpos.up()).getBlock().isNormalCube())
//            {
//                Entity entity = ItemMonsterPlacer.spawnCreature(worldIn, 57, (double)blockpos.getX() + 0.5D, (double)blockpos.getY() + 1.1D, (double)blockpos.getZ() + 0.5D);
//
//                if (entity != null)
//                {
//                    entity.portalTimer = entity.getPortalCooldown();
//                }
//            }
//        }
//    }

    public BoundingBox getCollisionBoundingBox(World worldIn, BlockPos pos, State state)
    {
        return null;
    }

    public void setBlockBoundsBasedOnState(IWorldAccess worldIn, BlockPos pos)
    {
        Facing.Axis enumfacing$axis = (Facing.Axis)worldIn.getState(pos).getValue(AXIS);
        float f = 0.125F;
        float f1 = 0.125F;

        if (enumfacing$axis == Facing.Axis.X)
        {
            f = 0.5F;
        }

        if (enumfacing$axis == Facing.Axis.Z)
        {
            f1 = 0.5F;
        }

        this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f1, 0.5F + f, 1.0F, 0.5F + f1);
    }

    public static int getMetaForAxis(Facing.Axis axis)
    {
        return axis == Facing.Axis.X ? 1 : (axis == Facing.Axis.Z ? 2 : 0);
    }

    public boolean isFullCube()
    {
        return false;
    }

    public boolean tryIgnitePortal(World worldIn, BlockPos pos, int dim)
    {
        BlockPortal.Size size = new BlockPortal.Size(worldIn, pos, Facing.Axis.X, dim);

        if (size.func_150860_b() && size.field_150864_e == 0)
        {
            size.func_150859_c();
            return true;
        }
        else
        {
            BlockPortal.Size size2 = new BlockPortal.Size(worldIn, pos, Facing.Axis.Z, dim);

            if (size2.func_150860_b() && size2.field_150864_e == 0)
            {
                size2.func_150859_c();
                return true;
            }
            else
            {
                return false;
            }
        }
    }

    /**
     * Called when a neighboring block changes.
     */
    public void onNeighborBlockChange(World worldIn, BlockPos pos, State state, Block neighborBlock)
    {
        Facing.Axis enumfacing$axis = (Facing.Axis)state.getValue(AXIS);
        int dim = state.getValue(DIM);

        if (enumfacing$axis == Facing.Axis.X)
        {
            BlockPortal.Size blockportal$size = new BlockPortal.Size(worldIn, pos, Facing.Axis.X, dim);

            if (!blockportal$size.func_150860_b() || blockportal$size.field_150864_e < blockportal$size.field_150868_h * blockportal$size.height)
            {
                worldIn.setState(pos, Blocks.air.getState());
            }
        }
        else if (enumfacing$axis == Facing.Axis.Z)
        {
            BlockPortal.Size blockportal$size1 = new BlockPortal.Size(worldIn, pos, Facing.Axis.Z, dim);

            if (!blockportal$size1.func_150860_b() || blockportal$size1.field_150864_e < blockportal$size1.field_150868_h * blockportal$size1.height)
            {
                worldIn.setState(pos, Blocks.air.getState());
            }
        }
    }

    public boolean shouldSideBeRendered(IWorldAccess worldIn, BlockPos pos, Facing side)
    {
        Facing.Axis enumfacing$axis = null;
        State iblockstate = worldIn.getState(pos);

        if (worldIn.getState(pos).getBlock() == this)
        {
            enumfacing$axis = (Facing.Axis)iblockstate.getValue(AXIS);

            if (enumfacing$axis == null)
            {
                return false;
            }

            if (enumfacing$axis == Facing.Axis.Z && side != Facing.EAST && side != Facing.WEST)
            {
                return false;
            }

            if (enumfacing$axis == Facing.Axis.X && side != Facing.SOUTH && side != Facing.NORTH)
            {
                return false;
            }
        }

        boolean flag = worldIn.getState(pos.west()).getBlock() == this && worldIn.getState(pos.west(2)).getBlock() != this;
        boolean flag1 = worldIn.getState(pos.east()).getBlock() == this && worldIn.getState(pos.east(2)).getBlock() != this;
        boolean flag2 = worldIn.getState(pos.north()).getBlock() == this && worldIn.getState(pos.north(2)).getBlock() != this;
        boolean flag3 = worldIn.getState(pos.south()).getBlock() == this && worldIn.getState(pos.south(2)).getBlock() != this;
        boolean flag4 = flag || flag1 || enumfacing$axis == Facing.Axis.X;
        boolean flag5 = flag2 || flag3 || enumfacing$axis == Facing.Axis.Z;
        return flag4 && side == Facing.WEST ? true : (flag4 && side == Facing.EAST ? true : (flag5 && side == Facing.NORTH ? true : flag5 && side == Facing.SOUTH));
    }

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

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

    /**
     * Called When an Entity Collided with the Block
     */
    public void onEntityCollidedWithBlock(World worldIn, BlockPos pos, State state, Entity entityIn)
    {
        if (entityIn.vehicle == null && entityIn.passenger == null)
        {
            entityIn.setPortal(state.getValue(DIM));
        }
    }

    public void randomDisplayTick(AWorldClient worldIn, BlockPos pos, State state, Random rand)
    {
//        if (rand.chance(100))
//        {
//            worldIn.playSound((double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, "portal.portal", 0.5F, rand.floatv() * 0.4F + 0.8F);
//        }

        for (int i = 0; i < 4; ++i)
        {
            double d0 = (double)((float)pos.getX() + rand.floatv());
            double d1 = (double)((float)pos.getY() + rand.floatv());
            double d2 = (double)((float)pos.getZ() + rand.floatv());
            double d3 = ((double)rand.floatv() - 0.5D) * 0.5D;
            double d4 = ((double)rand.floatv() - 0.5D) * 0.5D;
            double d5 = ((double)rand.floatv() - 0.5D) * 0.5D;
            int j = rand.zrange(2) * 2 - 1;

            if (worldIn.getState(pos.west()).getBlock() != this && worldIn.getState(pos.east()).getBlock() != this)
            {
                d0 = (double)pos.getX() + 0.5D + 0.25D * (double)j;
                d3 = (double)(rand.floatv() * 2.0F * (float)j);
            }
            else
            {
                d2 = (double)pos.getZ() + 0.5D + 0.25D * (double)j;
                d5 = (double)(rand.floatv() * 2.0F * (float)j);
            }

            worldIn.spawnParticle(ParticleType.PORTAL, d0, d1, d2, d3, d4, d5);
        }
    }

    public Item getItem(World worldIn, BlockPos pos)
    {
        return null;
    }

    public int getRenderColor(State state)
    {
        return COLORS[state.getValue(DIM)];
    }

    public int colorMultiplier(IWorldAccess worldIn, BlockPos pos, int renderPass)
    {
    	return this.getRenderColor(worldIn.getState(pos));
    }

    /**
     * Convert the given metadata into a BlockState for this Block
     */
    public State getStateFromMeta(int meta)
    {
        return this.getState().withProperty(AXIS, (meta & 8) == 8 ? Facing.Axis.Z : Facing.Axis.X)
        		.withProperty(DIM, meta & 7);
    }

    /**
     * Convert the BlockState into the correct metadata value
     */
    public int getMetaFromState(State state)
    {
        return (state.getValue(AXIS) == Axis.Z ? 8 : 0) | state.getValue(DIM);
    }

    protected IProperty[] getProperties()
    {
        return new IProperty[] {AXIS, DIM};
    }

    public Model getModel(ModelProvider provider, String name, State state) {
    	return state.getValue(AXIS) == Facing.Axis.X ? provider.getModel(name)
			.add(0, 0, 6, 16, 16, 10)
				.n().uv(0, 0, 16, 16).noCull().tint()
				.s().uv(0, 0, 16, 16).noCull().tint() : provider.getModel(name)
			.add(6, 0, 0, 10, 16, 16)
				.w().uv(0, 0, 16, 16).noCull().tint()
				.e().uv(0, 0, 16, 16).noCull().tint();
    }
    
    public void getAnimatedTextures(Map<String, Object> map) {
    	map.put("blocks/portal", 1);
    }

//    public BlockPattern.PatternHelper func_181089_f(World p_181089_1_, BlockPos p_181089_2_)
//    {
//        EnumFacing.Axis enumfacing$axis = EnumFacing.Axis.Z;
//        BlockPortal.Size blockportal$size = new BlockPortal.Size(p_181089_1_, p_181089_2_, EnumFacing.Axis.X);
//        LoadingCache<BlockPos, BlockWorldState> loadingcache = BlockPattern.createLoadingCache(p_181089_1_, true);
//
//        if (!blockportal$size.func_150860_b())
//        {
//            enumfacing$axis = EnumFacing.Axis.X;
//            blockportal$size = new BlockPortal.Size(p_181089_1_, p_181089_2_, EnumFacing.Axis.Z);
//        }
//
//        if (!blockportal$size.func_150860_b())
//        {
//            return new BlockPattern.PatternHelper(p_181089_2_, EnumFacing.NORTH, EnumFacing.UP, loadingcache, 1, 1, 1);
//        }
//        else
//        {
//            int[] aint = new int[EnumFacing.AxisDirection.values().length];
//            EnumFacing enumfacing = blockportal$size.field_150866_c.rotateYCCW();
//            BlockPos blockpos = blockportal$size.field_150861_f.up(blockportal$size.func_181100_a() - 1);
//
//            for (EnumFacing.AxisDirection enumfacing$axisdirection : EnumFacing.AxisDirection.values())
//            {
//                BlockPattern.PatternHelper blockpattern$patternhelper = new BlockPattern.PatternHelper(enumfacing.getAxisDirection() == enumfacing$axisdirection ? blockpos : blockpos.offset(blockportal$size.field_150866_c, blockportal$size.func_181101_b() - 1), EnumFacing.getFacingFromAxis(enumfacing$axisdirection, enumfacing$axis), EnumFacing.UP, loadingcache, blockportal$size.func_181101_b(), blockportal$size.func_181100_a(), 1);
//
//                for (int i = 0; i < blockportal$size.func_181101_b(); ++i)
//                {
//                    for (int j = 0; j < blockportal$size.func_181100_a(); ++j)
//                    {
//                        BlockWorldState blockworldstate = blockpattern$patternhelper.translateOffset(i, j, 1);
//
//                        if (blockworldstate.getBlockState() != null && blockworldstate.getBlockState().getBlock().getMaterial() != Material.air)
//                        {
//                            ++aint[enumfacing$axisdirection.ordinal()];
//                        }
//                    }
//                }
//            }
//
//            EnumFacing.AxisDirection enumfacing$axisdirection1 = EnumFacing.AxisDirection.POSITIVE;
//
//            for (EnumFacing.AxisDirection enumfacing$axisdirection2 : EnumFacing.AxisDirection.values())
//            {
//                if (aint[enumfacing$axisdirection2.ordinal()] < aint[enumfacing$axisdirection1.ordinal()])
//                {
//                    enumfacing$axisdirection1 = enumfacing$axisdirection2;
//                }
//            }
//
//            return new BlockPattern.PatternHelper(enumfacing.getAxisDirection() == enumfacing$axisdirection1 ? blockpos : blockpos.offset(blockportal$size.field_150866_c, blockportal$size.func_181101_b() - 1), EnumFacing.getFacingFromAxis(enumfacing$axisdirection1, enumfacing$axis), EnumFacing.UP, loadingcache, blockportal$size.func_181101_b(), blockportal$size.func_181100_a(), 1);
//        }
//    }

    public static class Size
    {
        private final World world;
        private final Facing.Axis axis;
        private final Facing field_150866_c;
        private final Facing field_150863_d;
        private final int dim;
        private int field_150864_e = 0;
        private BlockPos field_150861_f;
        private int height;
        private int field_150868_h;

        public Size(World worldIn, BlockPos p_i45694_2_, Facing.Axis p_i45694_3_, int dim)
        {
            this.world = worldIn;
            this.dim = dim;
            this.axis = p_i45694_3_;

            if (p_i45694_3_ == Facing.Axis.X)
            {
                this.field_150863_d = Facing.EAST;
                this.field_150866_c = Facing.WEST;
            }
            else
            {
                this.field_150863_d = Facing.NORTH;
                this.field_150866_c = Facing.SOUTH;
            }

            for (BlockPos blockpos = p_i45694_2_; p_i45694_2_.getY() > blockpos.getY() - 21 && p_i45694_2_.getY() > 0 && this.func_150857_a(worldIn.getState(p_i45694_2_.down()).getBlock()); p_i45694_2_ = p_i45694_2_.down())
            {
                ;
            }

            int i = this.func_180120_a(p_i45694_2_, this.field_150863_d) - 1;

            if (i >= 0)
            {
                this.field_150861_f = p_i45694_2_.offset(this.field_150863_d, i);
                this.field_150868_h = this.func_180120_a(this.field_150861_f, this.field_150866_c);

                if (this.field_150868_h < 2 || this.field_150868_h > 21)
                {
                    this.field_150861_f = null;
                    this.field_150868_h = 0;
                }
            }

            if (this.field_150861_f != null)
            {
                this.height = this.func_150858_a();
            }
        }

        protected int func_180120_a(BlockPos p_180120_1_, Facing p_180120_2_)
        {
            int i;

            for (i = 0; i < 22; ++i)
            {
                BlockPos blockpos = p_180120_1_.offset(p_180120_2_, i);

                if (!this.func_150857_a(this.world.getState(blockpos).getBlock()) || this.world.getState(blockpos.down()).getBlock() != Blocks.obsidian)
                {
                    break;
                }
            }

            Block block = this.world.getState(p_180120_1_.offset(p_180120_2_, i)).getBlock();
            return block == Blocks.obsidian ? i : 0;
        }

        public int func_181100_a()
        {
            return this.height;
        }

        public int func_181101_b()
        {
            return this.field_150868_h;
        }

        protected int func_150858_a()
        {
            label24:

            for (this.height = 0; this.height < 21; ++this.height)
            {
                for (int i = 0; i < this.field_150868_h; ++i)
                {
                    BlockPos blockpos = this.field_150861_f.offset(this.field_150866_c, i).up(this.height);
                    Block block = this.world.getState(blockpos).getBlock();

                    if (!this.func_150857_a(block))
                    {
                        break label24;
                    }

                    if (block == Blocks.portal)
                    {
                        ++this.field_150864_e;
                    }

                    if (i == 0)
                    {
                        block = this.world.getState(blockpos.offset(this.field_150863_d)).getBlock();

                        if (block != Blocks.obsidian)
                        {
                            break label24;
                        }
                    }
                    else if (i == this.field_150868_h - 1)
                    {
                        block = this.world.getState(blockpos.offset(this.field_150866_c)).getBlock();

                        if (block != Blocks.obsidian)
                        {
                            break label24;
                        }
                    }
                }
            }

            for (int j = 0; j < this.field_150868_h; ++j)
            {
                if (this.world.getState(this.field_150861_f.offset(this.field_150866_c, j).up(this.height)).getBlock() != Blocks.obsidian)
                {
                    this.height = 0;
                    break;
                }
            }

            if (this.height <= 21 && this.height >= 3)
            {
                return this.height;
            }
            else
            {
                this.field_150861_f = null;
                this.field_150868_h = 0;
                this.height = 0;
                return 0;
            }
        }

        protected boolean func_150857_a(Block p_150857_1_)
        {
            return p_150857_1_.material == Material.air || p_150857_1_ == Blocks.fire || p_150857_1_ == Blocks.portal;
        }

        public boolean func_150860_b()
        {
            return this.field_150861_f != null && this.field_150868_h >= 2 && this.field_150868_h <= 21 && this.height >= 3 && this.height <= 21;
        }

        public void func_150859_c()
        {
            for (int i = 0; i < this.field_150868_h; ++i)
            {
                BlockPos blockpos = this.field_150861_f.offset(this.field_150866_c, i);
                State state = Blocks.portal.getState().withProperty(BlockPortal.AXIS, this.axis)
                		.withProperty(DIM, this.dim);

                for (int j = 0; j < this.height; ++j)
                {
                    this.world.setState(blockpos.up(j), state, 2);
                }
            }
        }
    }
}
