package client.world;

import common.block.Block;
import common.init.Blocks;
import common.tileentity.TileEntity;
import common.util.BlockPos;
import common.util.NibbleArray;
import common.world.BlockArray;
import common.world.Chunk;
import common.world.World;

public class ChunkClient extends Chunk {
	private final float[] temperatures = new float[256];
	private final float[] offsets = new float[256];
	
	public ChunkClient(World world, int x, int z) {
		super(world, x, z);
	}
	
	private void clearArrays() {
		this.blocks.clearMap();
		this.blockList.clear();
		this.bottom = Integer.MAX_VALUE;
		this.top = Integer.MIN_VALUE;
	}

	private void genHeights() {
		int top = this.top;
		int bottom = this.bottom < -64 ? -64 : this.bottom;
		this.minHeight = Integer.MAX_VALUE;

		for(int x = 0; x < 16; ++x) {
			for(int z = 0; z < 16; ++z) {
				this.precHeight[x + (z << 4)] = Integer.MIN_VALUE;

				for(int y = top + 16; y > bottom; --y) {
					Block block = this.getBlock0(x, y - 1, z);

					if(block.getLightOpacity() != 0) {
						this.height[z << 4 | x] = y;

						if(y < this.minHeight) {
							this.minHeight = y;
						}

						break;
					}
				}
			}
		}

		this.modified = true;
	}
	
	public boolean isEmpty(int bottom, int top) {
		for(int y = bottom; y <= top; y += 16) {
			BlockArray stor = this.getArray(y >> 4);

			if(stor != null ? !stor.isEmpty() : (y < 0 && this.fillerBlock != Blocks.air)) {
				return false;
			}
		}

		return true;
	}

	public void setData(byte[] data, int[] extend, boolean biomes) {
		int pos = 0;
		
		if(biomes) {
			this.clearArrays();
		}
		for(int cy : extend) {
			BlockArray arr = this.getArray(cy);
			if(arr == null) {
				arr = new BlockArray(cy << 4, null);
				this.setArray(arr);
			}

			char[] blocks = arr.getData();

			for(int k = 0; k < blocks.length; ++k) {
				blocks[k] = (char)((data[pos + 1] & 255) << 8 | data[pos] & 255);
				pos += 2;
			}
		}

		for(int cy : extend) {
			BlockArray arr = this.getArray(cy);
			if(arr != null) {
				NibbleArray light = arr.getBlocklight();
				System.arraycopy(data, pos, light.getData(), 0, light.getData().length);
				pos += light.getData().length;
			}
		}

		if(biomes) {
			for(int k = 0; k < this.temperatures.length; ++k) {
				this.temperatures[k] = Float.intBitsToFloat((int)((data[pos + 3] & 255) << 24 | (data[pos + 2] & 255) << 16 | (data[pos + 1] & 255) << 8 | data[pos] & 255));
				pos += 4;
				this.offsets[k] = Float.intBitsToFloat((int)((data[pos + 3] & 255) << 24 | (data[pos + 2] & 255) << 16 | (data[pos + 1] & 255) << 8 | data[pos] & 255));
				pos += 4;
			}
		}
		
		for(int cy : extend) {
			BlockArray arr = this.getArray(cy);
			if(arr != null) {
				arr.update();
			}
		}

		this.lightInit = true;
		this.populated = true;
		this.genHeights();

		for(TileEntity tile : this.tiles.values()) {
			tile.resetBlock();
		}
	}
	
	public void setLoaded() {
		this.loaded = true;
	}

	public boolean isDummy() {
		return false;
	}
	
	public float getTemperature(BlockPos pos) {
		int x = pos.getX() & 15;
		int z = pos.getZ() & 15;
		return this.temperatures[z << 4 | x];
	}
	
	public float getOffset(BlockPos pos) {
		int x = pos.getX() & 15;
		int z = pos.getZ() & 15;
		return this.offsets[z << 4 | x];
	}
}
