package common.world;

import java.util.Arrays;

import common.block.Block;
import common.init.Blocks;
import common.util.NibbleArray;

public class BlockArray {
	private int yBase;
	private int blocks;
	private int ticked;
	private char[] data;
	private NibbleArray blocklight;
	private NibbleArray skylight;

	public BlockArray(int y, boolean sky, State filler) {
		this.yBase = y;
		this.data = new char[4096];
		this.blocklight = new NibbleArray();
		if(sky)
			this.skylight = new NibbleArray();
		if(filler != null && filler.getBlock() != Blocks.air) {
			Arrays.fill(this.data, (char)State.ID_MAP.get(filler));
			this.blocks = this.data.length;
			this.ticked = filler.getBlock().getTickRandomly() ? this.data.length : 0;
		}
	}

	public State get(int x, int y, int z) {
		State iblockstate = State.ID_MAP.getByValue(this.data[y << 8 | z << 4 | x]);
		return iblockstate != null ? iblockstate : Blocks.air.getState();
	}

	public void set(int x, int y, int z, State state) {
		State ostate = this.get(x, y, z);
		Block oblock = ostate.getBlock();
		Block block = state.getBlock();
		if(oblock != Blocks.air) {
			--this.blocks;
			if(oblock.getTickRandomly())
				--this.ticked;
		}
		if(block != Blocks.air) {
			++this.blocks;
			if(block.getTickRandomly())
				++this.ticked;
		}
		this.data[y << 8 | z << 4 | x] = (char)State.ID_MAP.get(state);
	}

	public Block getBlock(int x, int y, int z) {
		return this.get(x, y, z).getBlock();
	}

	public boolean isEmpty() {
		return this.blocks == 0;
	}

	public boolean isTicked() {
		return this.ticked > 0;
	}

	public int getY() {
		return this.yBase;
	}

	public void setSky(int x, int y, int z, int value) {
		this.skylight.set(x, y, z, value);
	}

	public int getSky(int x, int y, int z) {
		return this.skylight.get(x, y, z);
	}

	public void setLight(int x, int y, int z, int value) {
		this.blocklight.set(x, y, z, value);
	}

	public int getLight(int x, int y, int z) {
		return this.blocklight.get(x, y, z);
	}

	public void update() {
		this.blocks = 0;
		this.ticked = 0;
		for(int i = 0; i < 16; ++i) {
			for(int j = 0; j < 16; ++j) {
				for(int k = 0; k < 16; ++k) {
					Block block = this.getBlock(i, j, k);
					if(block != Blocks.air) {
						++this.blocks;
						if(block.getTickRandomly())
							++this.ticked;
					}
				}
			}
		}
	}

	public char[] getData() {
		return this.data;
	}

	public NibbleArray getBlocklight() {
		return this.blocklight;
	}

	public NibbleArray getSkylight() {
		return this.skylight;
	}

	public void setData(char[] data) {
		this.data = data;
	}

	public void setBlocklight(NibbleArray data) {
		this.blocklight = data;
	}

	public void setSkylight(NibbleArray data) {
		this.skylight = data;
	}
	
	public int hashCode() {
		return this.yBase >> 4;
	}
	
	public boolean equals(Object other) {
		return other instanceof BlockArray && ((BlockArray)other).yBase == this.yBase;
	}
}
