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

package com.hypixel.hytale.math.block;

import com.hypixel.hytale.math.vector.Vector3i;
import javax.annotation.Nonnull;
import com.hypixel.hytale.function.predicate.TriIntObjPredicate;

public class BlockCubeUtil
{
    public static <T> boolean forEachBlock(final int originX, final int originY, final int originZ, final int radiusX, final int height, final int radiusZ, final T t, @Nonnull final TriIntObjPredicate<T> consumer) {
        final int radiusY = height / 2;
        for (int dx = -radiusX; dx <= radiusX; ++dx) {
            for (int dz = -radiusZ; dz <= radiusZ; ++dz) {
                for (int dy = -radiusY; dy <= radiusY; ++dy) {
                    if (!consumer.test(originX + dx, originY + dy, originZ + dz, t)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
    
    public static <T> boolean forEachBlock(final int originX, final int originY, final int originZ, final int radiusX, final int height, final int radiusZ, final int thickness, final T t, @Nonnull final TriIntObjPredicate<T> consumer) {
        return forEachBlock(originX, originY, originZ, radiusX, height, radiusZ, thickness, false, t, consumer);
    }
    
    public static <T> boolean forEachBlock(final int originX, final int originY, final int originZ, final int radiusX, final int height, final int radiusZ, final int thickness, final boolean capped, final T t, @Nonnull final TriIntObjPredicate<T> consumer) {
        return forEachBlock(originX, originY, originZ, radiusX, height, radiusZ, thickness, capped, capped, false, t, consumer);
    }
    
    public static <T> boolean forEachBlock(final int originX, final int originY, final int originZ, final int radiusX, final int height, final int radiusZ, final int thickness, final boolean cappedTop, final boolean cappedBottom, final boolean hollow, final T t, @Nonnull final TriIntObjPredicate<T> consumer) {
        if (thickness < 1) {
            return forEachBlock(originX, originY, originZ, radiusX, height, radiusZ, t, consumer);
        }
        final int radiusY = height / 2;
        final int innerMinX = -radiusX + thickness;
        final int innerMaxX = radiusX - thickness;
        final int innerMinZ = -radiusZ + thickness;
        final int innerMaxZ = radiusZ - thickness;
        final int innerMinY = cappedBottom ? (-radiusY + thickness) : (-height);
        final int innerMaxY = cappedTop ? (radiusY - thickness) : height;
        for (int dx = -radiusX; dx <= radiusX; ++dx) {
            for (int dz = -radiusZ; dz <= radiusZ; ++dz) {
                for (int dy = -radiusY; dy <= radiusY; ++dy) {
                    if (dy < innerMinY || dy > innerMaxY || dx < innerMinX || dx > innerMaxX || dz < innerMinZ || dz > innerMaxZ) {
                        if (!consumer.test(originX + dx, originY + dy, originZ + dz, t)) {
                            return false;
                        }
                    }
                    else if (hollow && !consumer.test(originX + dx, originY + dy, originZ + dz, t)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
    
    public static <T> boolean forEachBlock(@Nonnull final Vector3i pointOne, @Nonnull final Vector3i pointTwo, final T t, @Nonnull final TriIntObjPredicate<T> consumer) {
        final Vector3i min = Vector3i.min(pointOne, pointTwo);
        final Vector3i max = Vector3i.max(pointOne, pointTwo);
        for (int x = min.x; x <= max.x; ++x) {
            for (int z = min.z; z <= max.z; ++z) {
                for (int y = min.y; y <= max.y; ++y) {
                    if (!consumer.test(x, y, z, t)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
    
    public static <T> boolean forEachBlock(@Nonnull final Vector3i pointOne, @Nonnull final Vector3i pointTwo, final int thickness, final boolean cappedTop, final boolean cappedBottom, final boolean hollow, final T t, @Nonnull final TriIntObjPredicate<T> consumer) {
        if (thickness < 1) {
            return forEachBlock(pointOne, pointTwo, t, consumer);
        }
        final Vector3i min = Vector3i.min(pointOne, pointTwo);
        final Vector3i max = Vector3i.max(pointOne, pointTwo);
        final int innerMinX = min.x + thickness;
        final int innerMaxX = max.x - thickness;
        final int innerMinZ = min.z + thickness;
        final int innerMaxZ = max.z - thickness;
        final int innerMinY = cappedBottom ? (min.y + thickness) : min.y;
        final int innerMaxY = cappedTop ? (max.y - thickness) : max.y;
        for (int x = min.x; x <= max.x; ++x) {
            for (int z = min.z; z <= max.z; ++z) {
                for (int y = min.y; y <= max.y; ++y) {
                    if (hollow) {
                        if (y >= innerMinY && y <= innerMaxY && x >= innerMinX && x <= innerMaxX && z >= innerMinZ && z <= innerMaxZ && !consumer.test(x, y, z, t)) {
                            return false;
                        }
                    }
                    else if ((y < innerMinY || y > innerMaxY || x < innerMinX || x > innerMaxX || z < innerMinZ || z > innerMaxZ) && !consumer.test(x, y, z, t)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
}
