package us.myles.ViaVersion.protocols.protocol1_14to1_13_2.types;

import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
import us.myles.ViaVersion.api.type.PartialType;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.types.minecraft.BaseChunkType;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.chunks.Chunk1_13;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.chunks.ChunkSection1_13;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;

public class Chunk1_14Type extends PartialType<Chunk, ClientWorld> {

	public Chunk1_14Type(ClientWorld param) {
		super(param, Chunk.class);
	}

	@Override
	public Chunk read(ByteBuf input, ClientWorld world) throws Exception {
		int chunkX = input.readInt();
		int chunkZ = input.readInt();

		boolean groundUp = input.readBoolean();
		int primaryBitmask = Type.VAR_INT.read(input);
		Type.VAR_INT.read(input);

		BitSet usedSections = new BitSet(16);
		ChunkSection1_13[] sections = new ChunkSection1_13[16];
		// Calculate section count from bitmask
		for (int i = 0; i < 16; i++) {
			if ((primaryBitmask & (1 << i)) != 0) {
				usedSections.set(i);
			}
		}

		// Read sections
		for (int i = 0; i < 16; i++) {
			if (!usedSections.get(i)) continue; // Section not set
			ChunkSection1_13 section = new ChunkSection1_13();
			sections[i] = section;
			input.readShort();  //TODO unknown short
			section.readBlocks(input);
		}

		byte[] biomeData = groundUp ? new byte[256] : null;
		if (groundUp) {
			for (int i = 0; i < 256; i++) {
				biomeData[i] = (byte) input.readInt();
			}
		}

		List<CompoundTag> nbtData = new ArrayList<>(Arrays.asList(Type.NBT_ARRAY.read(input)));

		// Read all the remaining bytes (workaround for #681)
		if (input.readableBytes() > 0) {
			byte[] array = Type.REMAINING_BYTES.read(input);
			if (Via.getManager().isDebug()) {
				Via.getPlatform().getLogger().warning("Found " + array.length + " more bytes than expected while reading the chunk: " + chunkX + "/" + chunkZ);
			}
		}

		return new Chunk1_13(chunkX, chunkZ, groundUp, primaryBitmask, sections, biomeData, nbtData);
	}

	@Override
	public void write(ByteBuf output, ClientWorld world, Chunk chunk) throws Exception {
		output.writeInt(chunk.getX());
		output.writeInt(chunk.getZ());

		output.writeBoolean(chunk.isGroundUp());
		Type.VAR_INT.write(output, chunk.getBitmask());

		ByteBuf buf = output.alloc().buffer();
		for (int i = 0; i < 16; i++) {
			ChunkSection section = chunk.getSections()[i];
			if (section == null) continue; // Section not set
			buf.writeShort(0);  //TODO find out what this short does (number of air blocks, important?)
			section.writeBlocks1_13(buf);
		}
		buf.readerIndex(0);
		Type.VAR_INT.write(output, buf.readableBytes() + (chunk.isBiomeData() ? 256 * 4 : 0));
		output.writeBytes(buf);
		buf.release(); // release buffer

		// Write biome data
		if (chunk.isBiomeData()) {
			for (byte value : chunk.getBiomeData()) {
				output.writeInt(value & 0xFF); // This is a temporary workaround, we'll look into fixing this soon :)
			}
		}

		// Write Block Entities
		Type.NBT_ARRAY.write(output, chunk.getBlockEntities().toArray(new CompoundTag[0]));
	}

	@Override
	public Class<? extends Type> getBaseClass() {
		return BaseChunkType.class;
	}
}

@@ -2884,17 +2884,20 @@
 teShort(
-0
+4096
 );  //TO

send 4096 in chunk data short