package net.minecraft.world;

import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

public class ChunkCache implements IBlockAccess
{
    protected int chunkX;
    protected int chunkZ;
    protected Chunk[][] chunkArray;
    /** set by !chunk.getAreLevelsEmpty */
    protected boolean hasExtendedLevels;
    /** Reference to the World object. */
    protected World worldObj;
    private static final String __OBFID = "CL_00000155";

    public ChunkCache(World worldIn, BlockPos p_i45746_2_, BlockPos p_i45746_3_, int p_i45746_4_)
    {
        this.worldObj = worldIn;
        this.chunkX = p_i45746_2_.getX() - p_i45746_4_ >> 4;
        this.chunkZ = p_i45746_2_.getZ() - p_i45746_4_ >> 4;
        int j = p_i45746_3_.getX() + p_i45746_4_ >> 4;
        int k = p_i45746_3_.getZ() + p_i45746_4_ >> 4;
        this.chunkArray = new Chunk[j - this.chunkX + 1][k - this.chunkZ + 1];
        this.hasExtendedLevels = true;
        int l;
        int i1;

        for (l = this.chunkX; l <= j; ++l)
        {
            for (i1 = this.chunkZ; i1 <= k; ++i1)
            {
                this.chunkArray[l - this.chunkX][i1 - this.chunkZ] = worldIn.getChunkFromChunkCoords(l, i1);
            }
        }

        for (l = p_i45746_2_.getX() >> 4; l <= p_i45746_3_.getX() >> 4; ++l)
        {
            for (i1 = p_i45746_2_.getZ() >> 4; i1 <= p_i45746_3_.getZ() >> 4; ++i1)
            {
                Chunk chunk = this.chunkArray[l - this.chunkX][i1 - this.chunkZ];

                if (chunk != null && !chunk.getAreLevelsEmpty(p_i45746_2_.getY(), p_i45746_3_.getY()))
                {
                    this.hasExtendedLevels = false;
                }
            }
        }
    }

    /**
     * set by !chunk.getAreLevelsEmpty
     */
    @SideOnly(Side.CLIENT)
    public boolean extendedLevelsInChunkCache()
    {
        return this.hasExtendedLevels;
    }

    public TileEntity getTileEntity(BlockPos pos)
    {
        int i = (pos.getX() >> 4) - this.chunkX;
        int j = (pos.getZ() >> 4) - this.chunkZ;
        if (i < 0 || i >= chunkArray.length || j < 0 || j >= chunkArray[i].length) return null;
        if (chunkArray[i][j] == null) return null;
        return this.chunkArray[i][j].func_177424_a(pos, Chunk.EnumCreateEntityType.IMMEDIATE);
    }

    @SideOnly(Side.CLIENT)
    public int getCombinedLight(BlockPos p_175626_1_, int p_175626_2_)
    {
        int j = this.func_175629_a(EnumSkyBlock.SKY, p_175626_1_);
        int k = this.func_175629_a(EnumSkyBlock.BLOCK, p_175626_1_);

        if (k < p_175626_2_)
        {
            k = p_175626_2_;
        }

        return j << 20 | k << 4;
    }

    public IBlockState getBlockState(BlockPos pos)
    {
        if (pos.getY() >= 0 && pos.getY() < 256)
        {
            int i = (pos.getX() >> 4) - this.chunkX;
            int j = (pos.getZ() >> 4) - this.chunkZ;
            if (i < 0 || i >= chunkArray.length || j < 0 || i >= chunkArray[i].length) return Blocks.air.getDefaultState();

            if (i >= 0 && i < this.chunkArray.length && j >= 0 && j < this.chunkArray[i].length)
            {
                Chunk chunk = this.chunkArray[i][j];

                if (chunk != null)
                {
                    return chunk.getBlockState(pos);
                }
            }
        }

        return Blocks.air.getDefaultState();
    }

    @SideOnly(Side.CLIENT)
    public BiomeGenBase getBiomeGenForCoords(BlockPos pos)
    {
        return this.worldObj.getBiomeGenForCoords(pos);
    }

    @SideOnly(Side.CLIENT)
    private int func_175629_a(EnumSkyBlock p_175629_1_, BlockPos p_175629_2_)
    {
        if (p_175629_1_ == EnumSkyBlock.SKY && this.worldObj.provider.getHasNoSky())
        {
            return 0;
        }
        else if (p_175629_2_.getY() >= 0 && p_175629_2_.getY() < 256)
        {
            int i;

            if (this.getBlockState(p_175629_2_).getBlock().getUseNeighborBrightness())
            {
                i = 0;
                EnumFacing[] aenumfacing = EnumFacing.values();
                int k = aenumfacing.length;

                for (int l = 0; l < k; ++l)
                {
                    EnumFacing enumfacing = aenumfacing[l];
                    int i1 = this.func_175628_b(p_175629_1_, p_175629_2_.offset(enumfacing));

                    if (i1 > i)
                    {
                        i = i1;
                    }

                    if (i >= 15)
                    {
                        return i;
                    }
                }

                return i;
            }
            else
            {
                i = (p_175629_2_.getX() >> 4) - this.chunkX;
                int j = (p_175629_2_.getZ() >> 4) - this.chunkZ;
                if (i < 0 || i >= chunkArray.length || j < 0 || j >= chunkArray[i].length) return p_175629_1_.defaultLightValue;
                if (chunkArray[i][j] == null) return p_175629_1_.defaultLightValue;
                return this.chunkArray[i][j].getLightFor(p_175629_1_, p_175629_2_);
            }
        }
        else
        {
            return p_175629_1_.defaultLightValue;
        }
    }

    public boolean isAirBlock(BlockPos pos)
    {
        return this.getBlockState(pos).getBlock().isAir(this, pos);
    }

    @SideOnly(Side.CLIENT)
    public int func_175628_b(EnumSkyBlock p_175628_1_, BlockPos p_175628_2_)
    {
        if (p_175628_2_.getY() >= 0 && p_175628_2_.getY() < 256)
        {
            int i = (p_175628_2_.getX() >> 4) - this.chunkX;
            int j = (p_175628_2_.getZ() >> 4) - this.chunkZ;
            if (i < 0 || i >= chunkArray.length || j < 0 || i >= chunkArray[i].length) return p_175628_1_.defaultLightValue;
            return this.chunkArray[i][j].getLightFor(p_175628_1_, p_175628_2_);
        }
        else
        {
            return p_175628_1_.defaultLightValue;
        }
    }

    public int getStrongPower(BlockPos pos, EnumFacing direction)
    {
        IBlockState iblockstate = this.getBlockState(pos);
        return iblockstate.getBlock().isProvidingStrongPower(this, pos, iblockstate, direction);
    }

    @SideOnly(Side.CLIENT)
    public WorldType getWorldType()
    {
        return this.worldObj.getWorldType();
    }

    @Override
    public boolean isSideSolid(BlockPos pos, EnumFacing side, boolean _default)
    {
        int x = (pos.getX() >> 4) - this.chunkX;
        int z = (pos.getZ() >> 4) - this.chunkZ;
        if (pos.getY() >= 0 && pos.getY() < 256) return _default;
        if (x < 0 || x >= chunkArray.length || z < 0 || x >= chunkArray[x].length) return _default;

        return getBlockState(pos).getBlock().isSideSolid(this, pos, side);
    }
}