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

package com.hypixel.hytale.procedurallib.supplier;

import java.util.Arrays;
import javax.annotation.Nonnull;
import java.util.Random;
import java.util.function.DoubleSupplier;

public class DoubleRange
{
    public static final Constant ZERO;
    public static final Constant ONE;
    
    static {
        ZERO = new Constant(0.0);
        ONE = new Constant(1.0);
    }
    
    public static class Constant implements IDoubleRange
    {
        protected final double result;
        
        public Constant(final double result) {
            this.result = result;
        }
        
        public double getResult() {
            return this.result;
        }
        
        @Override
        public double getValue(final double v) {
            return this.result;
        }
        
        @Override
        public double getValue(final DoubleSupplier supplier) {
            return this.result;
        }
        
        @Override
        public double getValue(final Random random) {
            return this.result;
        }
        
        @Override
        public double getValue(final int seed, final double x, final double y, final IDoubleCoordinateSupplier2d supplier) {
            return this.result;
        }
        
        @Override
        public double getValue(final int seed, final double x, final double y, final double z, final IDoubleCoordinateSupplier3d supplier) {
            return this.result;
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "DoubleRange.Constant{result=" + this.result;
        }
    }
    
    public static class Normal implements IDoubleRange
    {
        protected final double min;
        protected final double range;
        
        public Normal(final double min, final double max) {
            this.min = min;
            this.range = max - min;
        }
        
        public double getMin() {
            return this.min;
        }
        
        public double getRange() {
            return this.range;
        }
        
        @Override
        public double getValue(final double v) {
            return this.min + this.range * v;
        }
        
        @Override
        public double getValue(@Nonnull final DoubleSupplier supplier) {
            return this.min + this.range * supplier.getAsDouble();
        }
        
        @Override
        public double getValue(@Nonnull final Random random) {
            return this.getValue(random.nextDouble());
        }
        
        @Override
        public double getValue(final int seed, final double x, final double y, @Nonnull final IDoubleCoordinateSupplier2d supplier) {
            return this.min + this.range * supplier.get(seed, x, y);
        }
        
        @Override
        public double getValue(final int seed, final double x, final double y, final double z, @Nonnull final IDoubleCoordinateSupplier3d supplier) {
            return this.min + this.range * supplier.get(seed, x, y, z);
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "DoubleRange.Normal{min=" + this.min + ", range=" + this.range;
        }
    }
    
    public static class Multiple implements IDoubleRange
    {
        protected final double[] thresholds;
        protected final double[] values;
        
        public Multiple(final double[] thresholds, final double[] values) {
            this.thresholds = thresholds;
            this.values = values;
        }
        
        @Override
        public double getValue(final double v) {
            if (v > this.thresholds[this.thresholds.length - 1]) {
                return this.values[this.values.length - 1];
            }
            double min = 0.0;
            int i = 0;
            while (i < this.thresholds.length) {
                final double max = this.thresholds[i];
                if (v < max) {
                    if (i == 0) {
                        return this.values[0];
                    }
                    final double alpha = (v - min) / (max - min);
                    final double valueMin = this.values[i - 1];
                    final double valueMax = this.values[i];
                    final double range = valueMax - valueMin;
                    return valueMin + alpha * range;
                }
                else {
                    min = max;
                    ++i;
                }
            }
            return 0.0;
        }
        
        @Override
        public double getValue(@Nonnull final DoubleSupplier supplier) {
            return this.getValue(supplier.getAsDouble());
        }
        
        @Override
        public double getValue(@Nonnull final Random random) {
            return this.getValue(random.nextDouble());
        }
        
        @Override
        public double getValue(final int seed, final double x, final double y, @Nonnull final IDoubleCoordinateSupplier2d supplier) {
            return this.getValue(supplier.get(seed, x, y));
        }
        
        @Override
        public double getValue(final int seed, final double x, final double y, final double z, @Nonnull final IDoubleCoordinateSupplier3d supplier) {
            return this.getValue(supplier.get(seed, x, y, z));
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "Multiple{thresholds=" + Arrays.toString(this.thresholds) + ", values=" + Arrays.toString(this.values);
        }
    }
}
