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

package com.hypixel.hytale.procedurallib.condition;

import java.util.Arrays;
import javax.annotation.Nonnull;
import com.hypixel.hytale.procedurallib.property.NoiseProperty;

public class NoiseHeightThresholdInterpreter implements IHeightThresholdInterpreter
{
    protected final NoiseProperty noise;
    @Nonnull
    protected final float[] keys;
    @Nonnull
    protected final IHeightThresholdInterpreter[] values;
    protected final int length;
    protected final int lowestNonOne;
    protected final int highestNonZero;
    
    public NoiseHeightThresholdInterpreter(final NoiseProperty noise, @Nonnull final float[] keys, @Nonnull final IHeightThresholdInterpreter[] values) {
        if (keys.length != values.length) {
            throw new IllegalStateException("Length of keys and values are different!");
        }
        checkInterpreterLength(values);
        this.noise = noise;
        this.keys = keys;
        this.values = values;
        this.length = values[0].getLength();
        int lowestNonOne = 0;
        for (final IHeightThresholdInterpreter value : values) {
            if (value.getLowestNonOne() < lowestNonOne) {
                lowestNonOne = value.getLowestNonOne();
            }
        }
        this.lowestNonOne = lowestNonOne;
        int highestNonZero = this.length - 1;
        for (final IHeightThresholdInterpreter value2 : values) {
            if (value2.getHighestNonZero() > highestNonZero) {
                highestNonZero = value2.getHighestNonZero();
            }
        }
        this.highestNonZero = highestNonZero;
    }
    
    @Override
    public int getLowestNonOne() {
        return this.lowestNonOne;
    }
    
    @Override
    public int getHighestNonZero() {
        return this.highestNonZero;
    }
    
    protected double noise(final int seed, final double x, final double y) {
        return this.noise.get(seed, x, y);
    }
    
    @Override
    public double getContext(final int seed, final double x, final double y) {
        return this.noise(seed, x, y);
    }
    
    @Override
    public int getLength() {
        return this.length;
    }
    
    @Override
    public float getThreshold(final int seed, final double x, final double z, final int height) {
        return this.getThreshold(seed, x, z, height, this.getContext(seed, x, z));
    }
    
    @Override
    public float getThreshold(final int seed, final double x, final double z, final int height, final double context) {
        if (height > this.highestNonZero) {
            return 0.0f;
        }
        final int length = this.keys.length;
        int i = 0;
        while (i < length) {
            if (context <= this.keys[i]) {
                if (i == 0) {
                    return this.values[0].getThreshold(seed, x, z, height);
                }
                final float distance = ((float)context - this.keys[i - 1]) / (this.keys[i] - this.keys[i - 1]);
                return IHeightThresholdInterpreter.lerp(this.values[i - 1].getThreshold(seed, x, z, height), this.values[i].getThreshold(seed, x, z, height), distance);
            }
            else {
                ++i;
            }
        }
        return this.values[length - 1].getThreshold(seed, x, z, height);
    }
    
    static float lerp(final float from, final float to, final float t) {
        return from + (to - from) * t;
    }
    
    private static void checkInterpreterLength(@Nonnull final IHeightThresholdInterpreter[] values) {
        final int length = values[0].getLength();
        for (int i = 1; i < values.length; ++i) {
            if (values[i].getLength() != length) {
                throw new IllegalStateException("ThresholdKeyInterpreter have different size!");
            }
        }
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "NoiseHeightThresholdInterpreter{noise=" + String.valueOf(this.noise) + ", keys=" + Arrays.toString(this.keys) + ", values=" + Arrays.toString(this.values) + ", length=" + this.length + ", lowestNonOne=" + this.lowestNonOne + ", highestNonZero=" + this.highestNonZero;
    }
}
