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

package com.hypixel.hytale.builtin.buildertools;

import com.hypixel.hytale.builtin.buildertools.utils.Material;
import com.hypixel.hytale.server.core.universe.world.accessor.BlockAccessor;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import com.hypixel.hytale.server.core.universe.world.accessor.ChunkAccessor;
import com.hypixel.hytale.server.core.universe.world.accessor.LocalCachedChunkAccessor;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.server.core.prefab.selection.standard.BlockSelection;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.universe.world.accessor.OverridableChunkAccessor;
import com.hypixel.hytale.server.core.prefab.selection.mask.BlockMask;

public class EditOperation
{
    private final BlockMask blockMask;
    @Nonnull
    private final OverridableChunkAccessor accessor;
    @Nonnull
    private final BlockSelection before;
    @Nonnull
    private final BlockSelection after;
    private final Vector3i min;
    private final Vector3i max;
    
    public EditOperation(@Nonnull final World world, final int x, final int y, final int z, final int editRange, final Vector3i min, final Vector3i max, final BlockMask blockMask) {
        this.blockMask = blockMask;
        this.accessor = LocalCachedChunkAccessor.atWorldCoords(world, x, z, editRange);
        this.min = min;
        this.max = max;
        (this.before = new BlockSelection()).setPosition(x, y, z);
        if (min != null && max != null) {
            this.before.setSelectionArea(min, max);
        }
        this.after = new BlockSelection(this.before);
    }
    
    public BlockMask getBlockMask() {
        return this.blockMask;
    }
    
    @Nonnull
    public BlockSelection getBefore() {
        return this.before;
    }
    
    @Nonnull
    public BlockSelection getAfter() {
        return this.after;
    }
    
    @Nonnull
    public OverridableChunkAccessor getAccessor() {
        return this.accessor;
    }
    
    public int getBlock(final int x, final int y, final int z) {
        return this.accessor.getBlock(x, y, z);
    }
    
    public boolean setBlock(final int x, final int y, final int z, final int blockId) {
        return this.setBlock(x, y, z, blockId, 0);
    }
    
    public boolean setBlock(final int x, final int y, final int z, final int blockId, final int rotation) {
        final int currentBlock = this.getBlock(x, y, z);
        final int currentFluid = this.getFluid(x, y, z);
        if (this.blockMask != null && this.blockMask.isExcluded(this.accessor, x, y, z, this.min, this.max, currentBlock, currentFluid)) {
            return false;
        }
        final BlockAccessor blocks = this.accessor.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(x, z));
        if (blocks == null) {
            return false;
        }
        if (!this.before.hasBlockAtWorldPos(x, y, z)) {
            this.before.addBlockAtWorldPos(x, y, z, currentBlock, blocks.getRotationIndex(x, y, z), blocks.getFiller(x, y, z), blocks.getSupportValue(x, y, z), blocks.getBlockComponentHolder(x, y, z));
        }
        this.after.addBlockAtWorldPos(x, y, z, blockId, rotation, 0, 0);
        if (blockId == 0) {
            this.setFluid(x, y, z, 0, (byte)0);
        }
        return true;
    }
    
    private boolean setFluid(final int x, final int y, final int z, final int fluidId, final byte fluidLevel) {
        final BlockAccessor chunk = this.accessor.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(x, z));
        if (chunk == null) {
            return false;
        }
        final int currentBlock = this.getBlock(x, y, z);
        final int currentFluid = this.getFluid(x, y, z);
        if (this.blockMask != null && this.blockMask.isExcluded(this.accessor, x, y, z, this.min, this.max, currentBlock, currentFluid)) {
            return false;
        }
        final int beforeFluid = this.before.getFluidAtWorldPos(x, y, z);
        if (beforeFluid < 0) {
            final int originalFluidId = chunk.getFluidId(x, y, z);
            final byte originalFluidLevel = chunk.getFluidLevel(x, y, z);
            this.before.addFluidAtWorldPos(x, y, z, originalFluidId, originalFluidLevel);
        }
        this.after.addFluidAtWorldPos(x, y, z, fluidId, fluidLevel);
        return true;
    }
    
    public int getFluid(final int x, final int y, final int z) {
        final BlockAccessor chunk = this.accessor.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(x, z));
        if (chunk != null) {
            return chunk.getFluidId(x, y, z);
        }
        return 0;
    }
    
    public boolean setMaterial(final int x, final int y, final int z, @Nonnull final Material material) {
        if (material.isFluid()) {
            return this.setFluid(x, y, z, material.getFluidId(), material.getFluidLevel());
        }
        return this.setBlock(x, y, z, material.getBlockId(), material.getRotation());
    }
}
