// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.core.modules.collision;

import com.hypixel.hytale.server.core.asset.type.blockhitbox.BlockBoundingBoxes;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.universe.world.chunk.section.FluidSection;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.protocol.BlockMaterial;
import com.hypixel.hytale.server.core.asset.type.fluid.Fluid;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection;
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.core.universe.world.World;

public class BlockDataProvider extends BlockData
{
    protected static int FULL_LEVEL;
    protected final int INVALID_CHUNK_SECTION_INDEX = Integer.MIN_VALUE;
    @Nullable
    protected World world;
    @Nullable
    protected WorldChunk chunk;
    protected int chunkSectionIndex;
    @Nullable
    protected BlockSection chunkSection;
    protected int chunkX;
    protected int chunkY;
    protected int chunkZ;
    @Nullable
    protected Ref<ChunkStore> chunkSectionRef;
    
    public void initialize(final World world) {
        this.world = world;
        this.blockId = Integer.MIN_VALUE;
        this.cleanup0();
    }
    
    public void cleanup() {
        this.world = null;
        this.cleanup0();
    }
    
    public void read(final int x, final int y, final int z) {
        final int newBlockId = this.readBlockId(x, y, z);
        final int fluidId = this.readFluidId(x, y, z);
        if (this.blockId == newBlockId && this.fluidId == fluidId) {
            return;
        }
        if (newBlockId == 0 && fluidId == 0) {
            this.setBlock(0, BlockType.EMPTY, 0, 1);
            this.fluidId = 0;
            this.fluid = Fluid.EMPTY;
            this.fluidKey = "Empty";
            this.fillHeight = 0.0;
            return;
        }
        if (newBlockId == 1) {
            this.setBlock(1, BlockType.UNKNOWN, 0, 4);
            this.fluidId = 0;
            this.fluid = Fluid.EMPTY;
            this.fluidKey = "Empty";
            this.fillHeight = 0.0;
            return;
        }
        this.blockId = newBlockId;
        this.blockType = BlockType.getAssetMap().getAsset(newBlockId);
        if (this.blockType.isUnknown()) {
            this.setBlock(newBlockId, this.blockType, 0, 4);
            this.fluidId = 0;
            this.fluid = Fluid.EMPTY;
            this.fluidKey = "Empty";
            this.fillHeight = 0.0;
            return;
        }
        final Fluid fluid = Fluid.getAssetMap().getAsset(fluidId);
        final byte fluidLevel = this.readFluidLevel(x, y, z);
        this.blockTypeKey = this.blockType.getId();
        this.filler = this.readFiller(x, y, z);
        this.rotation = this.readRotation(x, y, z);
        if (this.blockType.getMaterial() == BlockMaterial.Solid) {
            this.collisionMaterials = 4;
            if (this.blockType.getHitboxTypeIndex() != 0) {
                this.collisionMaterials += materialFromFillLevel(fluid, fluidLevel);
            }
        }
        else {
            this.collisionMaterials = materialFromFillLevel(fluid, fluidLevel);
        }
        this.fluidId = fluidId;
        this.fluid = fluid;
        this.fluidKey = fluid.getId();
        this.fillHeight = ((fluidId != 0) ? (fluidLevel / (double)fluid.getMaxFluidLevel()) : 0.0);
        this.blockBoundingBoxes = null;
    }
    
    protected int readBlockId(final int x, final int y, final int z) {
        final int chunkX = ChunkUtil.chunkCoordinate(x);
        final int chunkZ = ChunkUtil.chunkCoordinate(z);
        if (this.chunk == null || this.chunk.getX() != chunkX || chunkZ != this.chunk.getZ()) {
            this.chunk = this.world.getChunkIfInMemory(ChunkUtil.indexChunk(chunkX, chunkZ));
            this.chunkSectionIndex = Integer.MIN_VALUE;
            this.chunkSection = null;
        }
        if (this.chunk == null) {
            return 1;
        }
        final int sectionIndex = ChunkUtil.indexSection(y);
        if (this.chunkSection == null || this.chunkSectionIndex != sectionIndex) {
            this.chunkSection = (((this.chunkSectionIndex = sectionIndex) >= 0 && this.chunkSectionIndex < 10) ? this.chunk.getBlockChunk().getSectionAtIndex(sectionIndex) : null);
        }
        if (this.chunkSection == null) {
            return 0;
        }
        return this.chunkSection.get(x, y, z);
    }
    
    protected int readRotation(final int x, final int y, final int z) {
        final int chunkX = ChunkUtil.chunkCoordinate(x);
        final int chunkZ = ChunkUtil.chunkCoordinate(z);
        if (this.chunk == null || this.chunk.getX() != chunkX || chunkZ != this.chunk.getZ()) {
            this.chunk = this.world.getChunkIfInMemory(ChunkUtil.indexChunk(chunkX, chunkZ));
            this.chunkSectionIndex = Integer.MIN_VALUE;
            this.chunkSection = null;
        }
        if (this.chunk == null) {
            return 0;
        }
        final int sectionIndex = ChunkUtil.indexSection(y);
        if (this.chunkSection == null || this.chunkSectionIndex != sectionIndex) {
            this.chunkSection = (((this.chunkSectionIndex = sectionIndex) >= 0 && this.chunkSectionIndex < 10) ? this.chunk.getBlockChunk().getSectionAtIndex(sectionIndex) : null);
        }
        if (this.chunkSection == null) {
            return 0;
        }
        return this.chunkSection.getRotationIndex(x, y, z);
    }
    
    protected int readFiller(final int x, final int y, final int z) {
        final int chunkX = ChunkUtil.chunkCoordinate(x);
        final int chunkZ = ChunkUtil.chunkCoordinate(z);
        if (this.chunk == null || this.chunk.getX() != chunkX || chunkZ != this.chunk.getZ()) {
            this.chunk = this.world.getChunkIfInMemory(ChunkUtil.indexChunk(chunkX, chunkZ));
            this.chunkSectionIndex = Integer.MIN_VALUE;
            this.chunkSection = null;
        }
        if (this.chunk == null) {
            return 0;
        }
        final int sectionIndex = ChunkUtil.indexSection(y);
        if (this.chunkSection == null || this.chunkSectionIndex != sectionIndex) {
            this.chunkSection = (((this.chunkSectionIndex = sectionIndex) >= 0 && this.chunkSectionIndex < 10) ? this.chunk.getBlockChunk().getSectionAtIndex(sectionIndex) : null);
        }
        if (this.chunkSection == null) {
            return 0;
        }
        return this.chunkSection.getFiller(x, y, z);
    }
    
    protected int readFluidId(final int x, final int y, final int z) {
        final int chunkX = ChunkUtil.chunkCoordinate(x);
        final int chunkY = ChunkUtil.chunkCoordinate(y);
        final int chunkZ = ChunkUtil.chunkCoordinate(z);
        if (this.chunkSectionRef == null || !this.chunkSectionRef.isValid() || this.chunkX != chunkX || this.chunkY != chunkY || this.chunkZ != chunkZ) {
            this.chunkSectionRef = this.world.getChunkStore().getChunkSectionReference(chunkX, chunkY, chunkZ);
            this.chunkX = chunkX;
            this.chunkY = chunkY;
            this.chunkZ = chunkZ;
        }
        if (this.chunkSectionRef == null) {
            return 1;
        }
        final FluidSection fluidSection = this.world.getChunkStore().getStore().getComponent(this.chunkSectionRef, FluidSection.getComponentType());
        if (fluidSection == null) {
            return 1;
        }
        return fluidSection.getFluidId(x, y, z);
    }
    
    protected byte readFluidLevel(final int x, final int y, final int z) {
        final int chunkX = ChunkUtil.chunkCoordinate(x);
        final int chunkY = ChunkUtil.chunkCoordinate(y);
        final int chunkZ = ChunkUtil.chunkCoordinate(z);
        if (this.chunkSectionRef == null || !this.chunkSectionRef.isValid() || this.chunkX != chunkX || this.chunkY != chunkY || this.chunkZ != chunkZ) {
            this.chunkSectionRef = this.world.getChunkStore().getChunkSectionReference(chunkX, chunkY, chunkZ);
            this.chunkX = chunkX;
            this.chunkY = chunkY;
            this.chunkZ = chunkZ;
        }
        if (this.chunkSectionRef == null) {
            return 0;
        }
        final FluidSection fluidSection = this.world.getChunkStore().getStore().getComponent(this.chunkSectionRef, FluidSection.getComponentType());
        if (fluidSection == null) {
            return 0;
        }
        return fluidSection.getFluidLevel(x, y, z);
    }
    
    protected void setBlock(final int id, @Nonnull final BlockType type, final int rotation, final int material, final BlockBoundingBoxes box) {
        this.blockId = id;
        this.rotation = rotation;
        this.blockType = type;
        this.blockTypeKey = type.getId();
        this.collisionMaterials = material;
        this.blockBoundingBoxes = box;
        this.fillHeight = 0.0;
    }
    
    protected void setBlock(final int id, @Nonnull final BlockType type, final int rotation, final int material) {
        this.setBlock(id, type, rotation, material, BlockBoundingBoxes.UNIT_BOX);
    }
    
    protected void cleanup0() {
        this.chunk = null;
        this.chunkSectionIndex = Integer.MIN_VALUE;
        this.chunkSection = null;
        this.blockType = null;
        this.blockTypeKey = null;
        this.blockBoundingBoxes = null;
        this.fluid = null;
        this.fluidKey = null;
    }
    
    protected static int materialFromFillLevel(@Nonnull final Fluid fluid, final byte level) {
        if (level == 0) {
            return 1;
        }
        if (level == fluid.getMaxFluidLevel()) {
            return 2;
        }
        return 3;
    }
    
    static {
        BlockDataProvider.FULL_LEVEL = 8;
    }
}
