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

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

import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import com.hypixel.hytale.procedurallib.logic.ResultBuffer;
import com.hypixel.hytale.procedurallib.logic.cell.evaluator.PointEvaluator;
import com.hypixel.hytale.procedurallib.logic.cell.CellDistanceFunction;

public class PointGenerator implements IPointGenerator
{
    protected final int seedOffset;
    protected final CellDistanceFunction cellDistanceFunction;
    protected final PointEvaluator pointEvaluator;
    
    public PointGenerator(final int seedOffset, final CellDistanceFunction cellDistanceFunction, final PointEvaluator pointEvaluator) {
        this.seedOffset = seedOffset;
        this.cellDistanceFunction = cellDistanceFunction;
        this.pointEvaluator = pointEvaluator;
    }
    
    @Nonnull
    protected ResultBuffer.Bounds2d localBounds2d() {
        return ResultBuffer.bounds2d;
    }
    
    @Nonnull
    protected ResultBuffer.ResultBuffer2d localBuffer2d() {
        return ResultBuffer.buffer2d;
    }
    
    @Nonnull
    protected ResultBuffer.ResultBuffer3d localBuffer3d() {
        return ResultBuffer.buffer3d;
    }
    
    @Nonnull
    @Override
    public ResultBuffer.ResultBuffer2d nearest2D(final int seed, double x, double y) {
        x = this.cellDistanceFunction.scale(x);
        y = this.cellDistanceFunction.scale(y);
        final int xr = this.cellDistanceFunction.getCellX(x, y);
        final int yr = this.cellDistanceFunction.getCellY(x, y);
        final ResultBuffer.ResultBuffer2d buffer = this.localBuffer2d();
        buffer.distance = Double.POSITIVE_INFINITY;
        this.cellDistanceFunction.nearest2D(seed + this.seedOffset, x, y, xr, yr, buffer, this.pointEvaluator);
        return buffer;
    }
    
    @Nonnull
    @Override
    public ResultBuffer.ResultBuffer3d nearest3D(final int seed, double x, double y, double z) {
        x = this.cellDistanceFunction.scale(x);
        y = this.cellDistanceFunction.scale(y);
        z = this.cellDistanceFunction.scale(z);
        final int xr = this.cellDistanceFunction.getCellX(x, y, z);
        final int yr = this.cellDistanceFunction.getCellY(x, y, z);
        final int zr = this.cellDistanceFunction.getCellZ(x, y, z);
        final ResultBuffer.ResultBuffer3d buffer = this.localBuffer3d();
        buffer.distance = Double.POSITIVE_INFINITY;
        this.cellDistanceFunction.nearest3D(seed + this.seedOffset, x, y, z, xr, yr, zr, buffer, this.pointEvaluator);
        return buffer;
    }
    
    @Nonnull
    @Override
    public ResultBuffer.ResultBuffer2d transition2D(final int seed, double x, double y) {
        x = this.cellDistanceFunction.scale(x);
        y = this.cellDistanceFunction.scale(y);
        final int xr = this.cellDistanceFunction.getCellX(x, y);
        final int yr = this.cellDistanceFunction.getCellY(x, y);
        final ResultBuffer.ResultBuffer2d buffer = this.localBuffer2d();
        buffer.distance = Double.POSITIVE_INFINITY;
        buffer.distance2 = Double.POSITIVE_INFINITY;
        this.cellDistanceFunction.transition2D(seed + this.seedOffset, x, y, xr, yr, buffer, this.pointEvaluator);
        return buffer;
    }
    
    @Nonnull
    @Override
    public ResultBuffer.ResultBuffer3d transition3D(final int seed, double x, double y, double z) {
        x = this.cellDistanceFunction.scale(x);
        y = this.cellDistanceFunction.scale(y);
        z = this.cellDistanceFunction.scale(z);
        final int xr = this.cellDistanceFunction.getCellX(x, y, z);
        final int yr = this.cellDistanceFunction.getCellY(x, y, z);
        final int zr = this.cellDistanceFunction.getCellZ(x, y, z);
        final ResultBuffer.ResultBuffer3d buffer = this.localBuffer3d();
        buffer.distance = Double.POSITIVE_INFINITY;
        buffer.distance2 = Double.POSITIVE_INFINITY;
        this.cellDistanceFunction.transition3D(seed + this.seedOffset, x, y, z, xr, yr, zr, buffer, this.pointEvaluator);
        return buffer;
    }
    
    @Override
    public double getInterval() {
        return 1.0;
    }
    
    @Override
    public void collect(final int seed, final double minX, final double minY, final double maxX, final double maxY, final PointConsumer2d consumer) {
        this.collect0(seed, minX, minY, maxX, maxY, (x, y, t) -> t.accept(x, y), consumer);
    }
    
    public void collect0(final int seed, double minX, double minY, double maxX, double maxY, final PointConsumer<PointConsumer2d> pointConsumer, final PointConsumer2d consumer) {
        minX = this.cellDistanceFunction.scale(minX);
        minY = this.cellDistanceFunction.scale(minY);
        maxX = this.cellDistanceFunction.scale(maxX);
        maxY = this.cellDistanceFunction.scale(maxY);
        final int x0 = this.cellDistanceFunction.getCellX(minX, minY);
        final int y0 = this.cellDistanceFunction.getCellY(minX, minY);
        final int x2 = this.cellDistanceFunction.getCellX(maxX, maxY);
        final int y2 = this.cellDistanceFunction.getCellY(maxX, maxY);
        final ResultBuffer.Bounds2d bounds = this.localBounds2d();
        bounds.assign(minX, minY, maxX, maxY);
        this.cellDistanceFunction.collect(seed, seed + this.seedOffset, x0, y0, x2, y2, bounds, consumer, pointConsumer, this.pointEvaluator);
    }
    
    @Override
    public boolean equals(@Nullable final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || this.getClass() != o.getClass()) {
            return false;
        }
        final PointGenerator that = (PointGenerator)o;
        return this.seedOffset == that.seedOffset && this.cellDistanceFunction.equals(that.cellDistanceFunction) && this.pointEvaluator.equals(that.pointEvaluator);
    }
    
    @Override
    public int hashCode() {
        int result = this.seedOffset;
        result = 31 * result + this.cellDistanceFunction.hashCode();
        result = 31 * result + this.pointEvaluator.hashCode();
        return result;
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "PointGenerator{seedOffset=" + this.seedOffset + ", cellDistanceFunction=" + String.valueOf(this.cellDistanceFunction) + ", pointEvaluator=" + String.valueOf(this.pointEvaluator);
    }
}
