// FIXME 1.15
//#if MC>=10800 && MC<11500
//$$ package com.replaymod.render.blend.exporters;
//$$
//$$ import com.replaymod.core.versions.MCVer;
//$$ import com.replaymod.render.blend.BlendMeshBuilder;
//$$ import com.replaymod.render.blend.BlendState;
//$$ import com.replaymod.render.blend.Exporter;
//$$ import com.replaymod.render.blend.data.DMesh;
//$$ import com.replaymod.render.blend.data.DObject;
//$$ import com.replaymod.render.blend.mixin.ContainerLocalRenderInformationAccessor;
//$$ import com.replaymod.render.blend.mixin.WorldRendererAccessor;
//$$ import de.johni0702.minecraft.gui.utils.lwjgl.vector.Vector3f;
//$$ import net.minecraft.client.MinecraftClient;
//$$ import net.minecraft.client.texture.SpriteAtlasTexture;
//$$ import net.minecraft.client.util.GlAllocationUtils;
//$$ import com.mojang.blaze3d.platform.GLX;
//$$ import net.minecraft.client.render.chunk.ChunkRenderData;
//$$ import net.minecraft.client.render.chunk.ChunkRenderer;
//$$ import net.minecraft.client.render.VertexFormats;
//$$ import net.minecraft.client.gl.VertexBuffer;
//$$ import org.apache.commons.lang3.tuple.Pair;
//$$ import org.lwjgl.opengl.GL11;
//$$ import org.lwjgl.opengl.GL15;
//$$
//#if MC>=10904
//$$ import net.minecraft.client.render.RenderLayer;
//$$ import net.minecraft.util.math.BlockPos;
//#else
//$$ import net.minecraft.util.BlockPos;
//$$ import net.minecraft.util.EnumWorldBlockLayer;
//#endif
//$$
//$$ import java.io.IOException;
//$$ import java.nio.ByteBuffer;
//$$ import java.util.ArrayList;
//$$ import java.util.EnumMap;
//$$ import java.util.HashMap;
//$$ import java.util.List;
//$$ import java.util.Map;
//$$
//$$ public class ChunkExporter implements Exporter {
//$$     private final Map<BlockPos, DObject> chunkObjects = new HashMap<>();
    //#if MC>=10904
    //$$ private final Map<BlockPos, Map<RenderLayer, DObject>> chunkLayerObjects = new HashMap<>();
    //$$ private final List<Pair<ChunkRenderer, RenderLayer>> chunks = new ArrayList<>();
    //#else
    //$$ private final Map<BlockPos, Map<EnumWorldBlockLayer, DObject>> chunkLayerObjects = new HashMap<>();
    //$$ private final List<Pair<RenderChunk, EnumWorldBlockLayer>> chunks = new ArrayList<>();
    //#endif
//$$     private DObject chunksObject;
//$$     private int frame;
//$$
//$$     public void addChunkUpdate(ChunkRenderer chunk, ChunkRenderData compiledChunk) {
        //#if MC>=10904
        //$$ for (RenderLayer layer : RenderLayer.values()) {
        //#else
        //$$ for (EnumWorldBlockLayer layer : EnumWorldBlockLayer.values()) {
        //#endif
//$$             if (compiledChunk == null || compiledChunk.isBufferInitialized(layer)) {
//$$                 chunks.add(Pair.of(chunk, layer));
//$$             }
//$$         }
//$$     }
//$$
//$$     @Override
//$$     public void setup() throws IOException {
//$$
//$$         MinecraftClient mc = MCVer.getMinecraft();
//$$         @SuppressWarnings("unchecked")
//$$         List<ContainerLocalRenderInformationAccessor> renderInfos = ((WorldRendererAccessor) mc.worldRenderer).getRenderInfos();
//$$         for (ContainerLocalRenderInformationAccessor renderInfo : renderInfos) {
//$$             ChunkRenderer renderChunk = renderInfo.getRenderChunk();
//$$             ChunkRenderData compiledChunk = renderChunk.getData();
//$$             if (!compiledChunk.isEmpty()) {
//$$                 addChunkUpdate(renderChunk, null);
//$$             }
//$$         }
//$$
//$$         chunksObject = new DObject(DObject.Type.OB_EMPTY);
//$$         chunksObject.id.name = "Chunks";
//$$         chunksObject.layers = 1 << 1;
//$$         BlendState.getState().getScene().base.add(chunksObject);
//$$     }
//$$
//$$     @Override
//$$     public void tearDown() throws IOException {
//$$         chunks.clear();
//$$         chunkObjects.clear();
//$$         chunksObject = null;
//$$     }
//$$
//$$     @Override
//$$     public void preFrame(int frame) throws IOException {
//$$         this.frame = frame;
//$$     }
//$$
//$$     @Override
//$$     public void postFrame(int frame) throws IOException {
        //#if MC>=10904
        //$$ for (Pair<ChunkRenderer, RenderLayer> pair : chunks) {
        //$$     RenderLayer layer = pair.getRight();
        //#else
        //$$ for (Pair<RenderChunk, EnumWorldBlockLayer> pair : chunks) {
        //$$     EnumWorldBlockLayer layer = pair.getRight();
        //#endif
//$$             ChunkRenderer chunk = pair.getLeft();
//$$             DObject chunkObject = chunkObjects.get(chunk.getOrigin());
//$$             if (chunkObject == null) {
//$$                 chunkObject = buildChunkObject(chunk);
//$$                 chunkObjects.put(chunk.getOrigin(), chunkObject);
//$$                 chunkLayerObjects.put(chunk.getOrigin(), new EnumMap<>(layer.getDeclaringClass()));
//$$             }
//$$             DObject layerObject = buildChunkLayerObject(chunkObject, chunk, layer);
//$$             if (layerObject == null) continue;
            //#if MC>=10904
            //$$ Map<RenderLayer, DObject> layerObjects
            //#else
            //$$ Map<EnumWorldBlockLayer, DObject> layerObjects
            //#endif
//$$                     = chunkLayerObjects.get(chunk.getOrigin());
//$$             DObject oldLayerObject = layerObjects.get(layer);
//$$             if (oldLayerObject != null) {
//$$                 oldLayerObject.keyframe("hide", 0, frame, 1f);
//$$             }
//$$             if (frame > 0) {
//$$                 layerObject.keyframe("hide", 0, frame - 1, 1f);
//$$                 layerObject.keyframe("hide", 0, frame, 0f);
//$$             } else {
//$$                 layerObject.keyframe("hide", 0, frame, 0f);
//$$             }
//$$             layerObjects.put(layer, layerObject);
//$$         }
//$$         chunks.clear();
//$$     }
//$$
//$$     private DObject buildChunkObject(ChunkRenderer renderChunk) {
//$$         BlockPos pos = renderChunk.getOrigin();
//$$         DObject chunkObject = new DObject(DObject.Type.OB_EMPTY);
//$$         chunkObject.setParent(chunksObject);
//$$         chunkObject.id.name = "Chunk[" + pos.getX()/16 + "/" + pos.getY()/16 + "/" + pos.getZ()/16 + "]";
//$$         chunkObject.loc = new Vector3f(pos.getX(), -pos.getZ(), pos.getY());
//$$         return chunkObject;
//$$     }
//$$
//$$     private DObject buildChunkLayerObject(DObject chunkObject, ChunkRenderer renderChunk,
                                          //#if MC>=10904
                                          //$$ RenderLayer layer) {
                                          //#else
                                          //$$ EnumWorldBlockLayer layer) {
                                          //#endif
//$$         VertexBuffer vertexBuffer = renderChunk.getGlBuffer(layer.ordinal());
//$$         if (vertexBuffer == null) return null;
//$$
//$$         DObject layerObject = new DObject(buildChunkLayerMesh(vertexBuffer));
//$$         layerObject.setParent(chunkObject);
//$$         layerObject.id.name = chunkObject.id.name + " - " + layer + " - Frame " + frame;
//$$         return layerObject;
//$$     }
//$$
//$$     private DMesh buildChunkLayerMesh(VertexBuffer vertexBuffer) {
//$$         vertexBuffer.bind();
//$$         int size = GL15.glGetBufferParameteri(GLX.GL_ARRAY_BUFFER, GL15.GL_BUFFER_SIZE);
//$$         ByteBuffer byteBuffer = GlAllocationUtils.allocateByteBuffer(size);
//$$         GL15.glGetBufferSubData(GLX.GL_ARRAY_BUFFER, 0, byteBuffer);
//$$         vertexBuffer.unbind();
//$$
//$$         MCVer.getMinecraft().getTextureManager().bindTexture(SpriteAtlasTexture.BLOCK_ATLAS_TEX);
//$$
//$$         return BlendMeshBuilder.addBufferToMesh(byteBuffer, GL11.GL_QUADS, VertexFormats.POSITION_COLOR_UV_LMAP, null, null);
//$$     }
//$$
//$$     private static final int STRIDE = 28;
//$$ }
//#endif
