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

package com.hypixel.hytale.builtin.hytalegenerator.framework.math;

import javax.annotation.Nonnull;

public class Splitter
{
    @Nonnull
    public static Range[] split(@Nonnull final Range range, final int pieces) {
        if (pieces < 0) {
            throw new IllegalArgumentException("negative number of pieces");
        }
        final int size = range.max - range.min;
        int pieceSize = size / pieces;
        if (size % pieces > 0) {
            ++pieceSize;
        }
        final Range[] output = new Range[pieces];
        for (int i = 0; i < output.length; ++i) {
            final int min = Math.min(i * pieceSize + range.min, range.max);
            final int max = Math.min(min + pieceSize, range.max);
            output[i] = new Range(min, max);
        }
        return output;
    }
    
    @Nonnull
    public static Area[] split(@Nonnull final Area area, int pieces) {
        if (pieces < 1) {
            throw new IllegalArgumentException("negative number of pieces");
        }
        if (pieces == 1) {
            return new Area[] { area };
        }
        final int sizeX = area.maxX - area.minX;
        final int sizeZ = area.maxZ - area.minZ;
        if (pieces > sizeX) {
            pieces = sizeX;
        }
        final Area[] output = new Area[pieces];
        if (pieces % 3 == 0) {
            final Range[] rangesX = split(new Range(area.minX, area.maxX), 3);
            final Range[] rangesZ = split(new Range(area.minZ, area.maxZ), pieces / 3);
            int o = 0;
            for (final Range x : rangesX) {
                for (final Range range : rangesZ) {
                    output[o++] = new Area(x.min, range.min, x.max, range.max);
                }
            }
        }
        else if (pieces % 2 == 0) {
            final Range[] rangesX = split(new Range(area.minX, area.maxX), 2);
            final Range[] rangesZ = split(new Range(area.minZ, area.maxZ), pieces / 2);
            int o = 0;
            for (final Range x : rangesX) {
                for (final Range range : rangesZ) {
                    output[o++] = new Area(x.min, range.min, x.max, range.max);
                }
            }
        }
        else {
            final Range[] ranges = split(new Range(area.minX, area.maxX), pieces);
            for (int i = 0; i < ranges.length; ++i) {
                output[i] = new Area(ranges[i].min, area.minZ, ranges[i].max, area.maxZ);
            }
        }
        return output;
    }
    
    @Nonnull
    public static Area[] splitX(@Nonnull final Area area, int pieces) {
        if (pieces < 1) {
            throw new IllegalArgumentException("negative number of pieces");
        }
        if (pieces == 1) {
            return new Area[] { area };
        }
        final int sizeX = area.maxX - area.minX;
        final int sizeZ = area.maxZ - area.minZ;
        if (pieces > sizeX) {
            pieces = sizeX;
        }
        final Area[] output = new Area[pieces];
        final Range[] ranges = split(new Range(area.minX, area.maxX), pieces);
        for (int i = 0; i < ranges.length; ++i) {
            output[i] = new Area(ranges[i].min, area.minZ, ranges[i].max, area.maxZ);
        }
        return output;
    }
    
    public static class Area
    {
        public final int minX;
        public final int minZ;
        public final int maxX;
        public final int maxZ;
        
        public Area(final int minX, final int minZ, final int maxX, final int maxZ) {
            if (maxX < minX || maxZ < minZ) {
                throw new IllegalArgumentException("max smaller than min");
            }
            this.minX = minX;
            this.minZ = minZ;
            this.maxX = maxX;
            this.maxZ = maxZ;
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "Area{minX=" + this.minX + ", minZ=" + this.minZ + ", maxX=" + this.maxX + ", maxZ=" + this.maxZ;
        }
    }
    
    public static class Range
    {
        public final int min;
        public final int max;
        
        public Range(final int min, final int max) {
            if (max < min) {
                throw new IllegalArgumentException("max smaller than min");
            }
            this.min = min;
            this.max = max;
        }
    }
}
