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

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

import com.hypixel.hytale.codec.codecs.EnumCodec;
import com.hypixel.hytale.codec.Codec;
import java.util.Iterator;
import java.util.Collections;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.builtin.hytalegenerator.VectorUtil;
import com.hypixel.hytale.builtin.hytalegenerator.framework.math.Calculator;
import java.util.ArrayList;
import com.hypixel.hytale.builtin.hytalegenerator.bounds.SpaceSize;
import com.hypixel.hytale.math.vector.Vector2i;
import java.util.List;
import javax.annotation.Nonnull;

public class AreaScanner extends Scanner
{
    @Nonnull
    private final ScanShape scanShape;
    private final int range;
    private final int resultCap;
    @Nonnull
    private final Scanner childScanner;
    @Nonnull
    private final List<Vector2i> scanOrder;
    @Nonnull
    private final SpaceSize scanSpaceSize;
    
    public AreaScanner(final int resultCap, @Nonnull final ScanShape scanShape, final int range, @Nonnull final Scanner childScanner) {
        if (resultCap < 0 || range < 0) {
            throw new IllegalArgumentException();
        }
        this.resultCap = resultCap;
        this.childScanner = childScanner;
        this.scanShape = scanShape;
        this.range = range;
        final ArrayList<Vector2i> scanOrder = new ArrayList<Vector2i>();
        for (int x = -range; x <= range; ++x) {
            for (int z = -range; z <= range; ++z) {
                if (scanShape != ScanShape.CIRCLE || Calculator.distance(x, z, 0.0, 0.0) <= range) {
                    scanOrder.add(new Vector2i(x, z));
                }
            }
        }
        this.scanOrder = VectorUtil.orderByDistanceFrom(new Vector2i(), scanOrder);
        this.scanSpaceSize = new SpaceSize(new Vector3i(-range, 0, -range), new Vector3i(1 + range, 0, 1 + range));
    }
    
    @Nonnull
    @Override
    public List<Vector3i> scan(@Nonnull final Context context) {
        if (this.resultCap == 0) {
            return Collections.emptyList();
        }
        final ArrayList<Vector3i> validPositions = new ArrayList<Vector3i>(this.resultCap);
        for (final Vector2i column : this.scanOrder) {
            final Vector3i columnOrigin = new Vector3i(context.position.x + column.x, context.position.y, context.position.z + column.y);
            final Context childContext = new Context(columnOrigin, context.pattern, context.materialSpace, context.workerId);
            final List<Vector3i> results = this.childScanner.scan(childContext);
            for (final Vector3i result : results) {
                validPositions.add(result);
                if (validPositions.size() == this.resultCap) {
                    return validPositions;
                }
            }
        }
        return validPositions;
    }
    
    @Nonnull
    @Override
    public SpaceSize scanSpace() {
        return this.scanSpaceSize.clone();
    }
    
    public enum Verticality
    {
        GLOBAL, 
        LOCAL;
    }
    
    public enum ScanShape
    {
        CIRCLE, 
        SQUARE;
        
        public static final Codec<ScanShape> CODEC;
        
        static {
            CODEC = new EnumCodec<ScanShape>(ScanShape.class, EnumCodec.EnumStyle.LEGACY);
        }
    }
}
