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

package com.hypixel.hytale.procedurallib.logic.cell;

import com.hypixel.hytale.math.util.HashUtil;
import com.hypixel.hytale.procedurallib.logic.point.PointConsumer;
import com.hypixel.hytale.procedurallib.logic.cell.jitter.CellJitter;
import com.hypixel.hytale.procedurallib.logic.DoubleArray;
import com.hypixel.hytale.procedurallib.logic.CellularNoise;
import javax.annotation.Nonnull;
import com.hypixel.hytale.procedurallib.logic.cell.evaluator.PointEvaluator;
import com.hypixel.hytale.procedurallib.logic.ResultBuffer;

public class GridCellDistanceFunction implements CellDistanceFunction
{
    public static final GridCellDistanceFunction DISTANCE_FUNCTION;
    public static final CellPointFunction POINT_FUNCTION;
    
    @Override
    public void nearest2D(final int seed, final double x, final double y, final int cellX, final int cellY, final ResultBuffer.ResultBuffer2d buffer, @Nonnull final PointEvaluator pointEvaluator) {
        for (int cy = cellY - 1; cy <= cellY + 1; ++cy) {
            for (int cx = cellX - 1; cx <= cellX + 1; ++cx) {
                this.evalPoint(seed, x, y, cx, cy, buffer, pointEvaluator);
            }
        }
    }
    
    @Override
    public void nearest3D(final int seed, final double x, final double y, final double z, final int cellX, final int cellY, final int cellZ, final ResultBuffer.ResultBuffer3d buffer, @Nonnull final PointEvaluator pointEvaluator) {
        for (int cx = cellX - 1; cx <= cellX + 1; ++cx) {
            for (int cy = cellY - 1; cy <= cellY + 1; ++cy) {
                for (int cz = cellZ - 1; cz <= cellZ + 1; ++cz) {
                    this.evalPoint(seed, x, y, z, cx, cy, cz, buffer, pointEvaluator);
                }
            }
        }
    }
    
    @Override
    public void transition2D(final int seed, final double x, final double y, final int cellX, final int cellY, final ResultBuffer.ResultBuffer2d buffer, @Nonnull final PointEvaluator pointEvaluator) {
        for (int cy = cellY - 1; cy <= cellY + 1; ++cy) {
            for (int cx = cellX - 1; cx <= cellX + 1; ++cx) {
                this.evalPoint2(seed, x, y, cx, cy, buffer, pointEvaluator);
            }
        }
    }
    
    @Override
    public void transition3D(final int seed, final double x, final double y, final double z, final int cellX, final int cellY, final int cellZ, final ResultBuffer.ResultBuffer3d buffer, @Nonnull final PointEvaluator pointEvaluator) {
        for (int cx = cellX - 1; cx <= cellX + 1; ++cx) {
            for (int cy = cellY - 1; cy <= cellY + 1; ++cy) {
                for (int cz = cellZ - 1; cz <= cellZ + 1; ++cz) {
                    this.evalPoint2(seed, x, y, z, cx, cy, cz, buffer, pointEvaluator);
                }
            }
        }
    }
    
    @Override
    public void evalPoint(final int seed, final double x, final double y, final int cellX, final int cellY, final ResultBuffer.ResultBuffer2d buffer, @Nonnull final PointEvaluator pointEvaluator) {
        final int cellHash = getHash(seed, cellX, cellY);
        final DoubleArray.Double2 vec = CellularNoise.CELL_2D[cellHash & 0xFF];
        final CellJitter jitter = pointEvaluator.getJitter();
        final double px = jitter.getPointX(cellX, vec);
        final double py = jitter.getPointY(cellY, vec);
        pointEvaluator.evalPoint(seed, x, y, cellHash, cellX, cellY, px, py, buffer);
    }
    
    @Override
    public void evalPoint(final int seed, final double x, final double y, final double z, final int cellX, final int cellY, final int cellZ, final ResultBuffer.ResultBuffer3d buffer, @Nonnull final PointEvaluator pointEvaluator) {
        final int cellHash = getHash(seed, cellX, cellY);
        final DoubleArray.Double3 vec = CellularNoise.CELL_3D[cellHash & 0xFF];
        final CellJitter jitter = pointEvaluator.getJitter();
        final double px = jitter.getPointX(cellX, vec);
        final double py = jitter.getPointY(cellX, vec);
        final double pz = jitter.getPointZ(cellX, vec);
        pointEvaluator.evalPoint(seed, x, y, z, cellHash, cellX, cellY, cellZ, px, py, pz, buffer);
    }
    
    @Override
    public void evalPoint2(final int seed, final double x, final double y, final int cellX, final int cellY, final ResultBuffer.ResultBuffer2d buffer, @Nonnull final PointEvaluator pointEvaluator) {
        final int cellHash = getHash(seed, cellX, cellY);
        final DoubleArray.Double2 vec = CellularNoise.CELL_2D[cellHash & 0xFF];
        final CellJitter jitter = pointEvaluator.getJitter();
        final double px = jitter.getPointX(cellX, vec);
        final double py = jitter.getPointY(cellY, vec);
        pointEvaluator.evalPoint2(seed, x, y, cellHash, cellX, cellY, px, py, buffer);
    }
    
    @Override
    public void evalPoint2(final int seed, final double x, final double y, final double z, final int cellX, final int cellY, final int cellZ, final ResultBuffer.ResultBuffer3d buffer, @Nonnull final PointEvaluator pointEvaluator) {
        final int cellHash = getHash(seed, cellX, cellY);
        final DoubleArray.Double3 vec = CellularNoise.CELL_3D[cellHash & 0xFF];
        final CellJitter jitter = pointEvaluator.getJitter();
        final double px = jitter.getPointX(cellX, vec);
        final double py = jitter.getPointY(cellX, vec);
        final double pz = jitter.getPointZ(cellX, vec);
        pointEvaluator.evalPoint2(seed, x, y, z, cellHash, cellX, cellY, cellZ, px, py, pz, buffer);
    }
    
    @Override
    public <T> void collect(final int originalSeed, final int seed, final int minX, final int minY, final int maxX, final int maxY, final ResultBuffer.Bounds2d bounds, final T ctx, @Nonnull final PointConsumer<T> collector, @Nonnull final PointEvaluator pointEvaluator) {
        final CellJitter jitter = pointEvaluator.getJitter();
        for (int cy = minY; cy <= maxY; ++cy) {
            for (int cx = minX; cx <= maxX; ++cx) {
                final int cellHash = getHash(seed, cx, cy);
                final DoubleArray.Double2 vec = CellularNoise.CELL_2D[cellHash & 0xFF];
                final double px = jitter.getPointX(cx, vec);
                final double py = jitter.getPointY(cy, vec);
                pointEvaluator.collectPoint(cellHash, cx, cy, px, py, ctx, collector);
            }
        }
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "GridCellFunction{}";
    }
    
    public static int getHash(final int seed, final int cellX, final int cellY) {
        return (int)HashUtil.rehash(seed, cellX, cellY);
    }
    
    static {
        DISTANCE_FUNCTION = new GridCellDistanceFunction();
        POINT_FUNCTION = new CellPointFunction() {
            @Override
            public int getHash(final int seed, final int cellX, final int cellY) {
                return GridCellDistanceFunction.getHash(seed, cellX, cellY);
            }
            
            @Override
            public DoubleArray.Double2 getOffsets(final int hash) {
                return CellularNoise.CELL_2D[hash & 0xFF];
            }
            
            @Override
            public double getX(final double x, final double y) {
                return x;
            }
            
            @Override
            public double getY(final double x, final double y) {
                return y;
            }
        };
    }
}
