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

package com.hypixel.hytale.builtin.hytalegenerator.props;

import org.checkerframework.checker.nullness.compatqual.NonNullDecl;
import java.util.Iterator;
import java.util.List;
import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer;
import com.hypixel.hytale.builtin.hytalegenerator.datastructures.voxelspace.VoxelSpace;
import com.hypixel.hytale.builtin.hytalegenerator.newsystem.GridUtils;
import com.hypixel.hytale.builtin.hytalegenerator.bounds.SpaceSize;
import com.hypixel.hytale.builtin.hytalegenerator.VectorUtil;
import javax.annotation.Nonnull;
import com.hypixel.hytale.builtin.hytalegenerator.bounds.Bounds3i;
import com.hypixel.hytale.builtin.hytalegenerator.conveyor.stagedconveyor.ContextDependency;
import com.hypixel.hytale.builtin.hytalegenerator.patterns.Pattern;
import com.hypixel.hytale.builtin.hytalegenerator.scanners.Scanner;
import com.hypixel.hytale.builtin.hytalegenerator.material.Material;
import com.hypixel.hytale.math.vector.Vector3i;

public class BoxProp extends Prop
{
    private final Vector3i range;
    private final Material material;
    private final Scanner scanner;
    private final Pattern pattern;
    private final ContextDependency contextDependency;
    private final Bounds3i readBounds_voxelGrid;
    private final Bounds3i writeBounds_voxelGrid;
    private final Bounds3i boxBounds_voxelGrid;
    
    public BoxProp(final Vector3i range, @Nonnull final Material material, @Nonnull final Scanner scanner, @Nonnull final Pattern pattern) {
        if (VectorUtil.isAnySmaller(range, new Vector3i())) {
            throw new IllegalArgumentException("negative range");
        }
        this.range = range.clone();
        this.material = material;
        this.scanner = scanner;
        this.pattern = pattern;
        SpaceSize writeSpace = new SpaceSize(new Vector3i(-range.x - 1, 0, -range.z - 1), new Vector3i(range.x + 2, 0, range.z + 2));
        writeSpace = SpaceSize.stack(writeSpace, scanner.readSpaceWith(pattern));
        final Vector3i writeRange = writeSpace.getRange();
        final Vector3i readRange = scanner.readSpaceWith(pattern).getRange();
        this.contextDependency = new ContextDependency(readRange, writeRange);
        this.readBounds_voxelGrid = this.contextDependency.getReadBounds_voxelGrid();
        this.writeBounds_voxelGrid = this.contextDependency.getWriteBounds_voxelGrid();
        this.boxBounds_voxelGrid = GridUtils.createBounds_fromVector_originVoxelInclusive(range);
    }
    
    @Override
    public PositionListScanResult scan(@Nonnull final Vector3i position, @Nonnull final VoxelSpace<Material> materialSpace, @Nonnull final WorkerIndexer.Id id) {
        final Scanner.Context scannerContext = new Scanner.Context(position, this.pattern, materialSpace, id);
        final List<Vector3i> validPositions = this.scanner.scan(scannerContext);
        return new PositionListScanResult(validPositions);
    }
    
    @Override
    public void place(@Nonnull final Context context) {
        final List<Vector3i> positions = PositionListScanResult.cast(context.scanResult).getPositions();
        if (positions == null) {
            return;
        }
        final Bounds3i writeSpaceBounds_voxelGrid = context.materialSpace.getBounds();
        for (final Vector3i position : positions) {
            final Bounds3i localBoxBounds_voxelGrid = this.boxBounds_voxelGrid.clone().offset(position);
            if (!localBoxBounds_voxelGrid.intersects(writeSpaceBounds_voxelGrid)) {
                continue;
            }
            this.place(position, context.materialSpace);
        }
    }
    
    private void place(@Nonnull final Vector3i position, @Nonnull final VoxelSpace<Material> materialSpace) {
        final Vector3i min = position.clone().add(-this.range.x, 0, -this.range.z);
        final Vector3i max = position.clone().add(this.range.x, this.range.y + this.range.y, this.range.z);
        for (int x = min.x; x <= max.x; ++x) {
            for (int y = min.y; y <= max.y; ++y) {
                for (int z = min.z; z <= max.z; ++z) {
                    if (materialSpace.isInsideSpace(x, y, z)) {
                        materialSpace.set(this.material, x, y, z);
                    }
                }
            }
        }
    }
    
    @Override
    public ContextDependency getContextDependency() {
        return this.contextDependency.clone();
    }
    
    @NonNullDecl
    @Override
    public Bounds3i getReadBounds_voxelGrid() {
        return this.readBounds_voxelGrid;
    }
    
    @Nonnull
    @Override
    public Bounds3i getWriteBounds_voxelGrid() {
        return this.writeBounds_voxelGrid;
    }
}
