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

package com.hypixel.hytale.procedurallib.json;

import com.google.gson.JsonArray;
import com.hypixel.hytale.procedurallib.supplier.DoubleRange;
import java.util.Objects;
import com.google.gson.JsonElement;
import java.nio.file.Path;
import javax.annotation.Nonnull;
import com.hypixel.hytale.procedurallib.supplier.IDoubleRange;

public class DoubleRangeJsonLoader<K extends SeedResource> extends JsonLoader<K, IDoubleRange>
{
    protected final double default1;
    protected final double default2;
    @Nonnull
    protected final DoubleToDoubleFunction function;
    
    public DoubleRangeJsonLoader(@Nonnull final SeedString<K> seed, final Path dataFolder, final JsonElement json) {
        this(seed, dataFolder, json, 0.0, d -> d);
    }
    
    public DoubleRangeJsonLoader(@Nonnull final SeedString<K> seed, final Path dataFolder, final JsonElement json, final DoubleToDoubleFunction function) {
        this(seed, dataFolder, json, 0.0, function);
    }
    
    public DoubleRangeJsonLoader(@Nonnull final SeedString<K> seed, final Path dataFolder, final JsonElement json, final double default1) {
        this(seed, dataFolder, json, default1, default1, d -> d);
    }
    
    public DoubleRangeJsonLoader(@Nonnull final SeedString<K> seed, final Path dataFolder, final JsonElement json, final double default1, final DoubleToDoubleFunction function) {
        this(seed, dataFolder, json, default1, default1, function);
    }
    
    public DoubleRangeJsonLoader(@Nonnull final SeedString<K> seed, final Path dataFolder, final JsonElement json, final double default1, final double default2) {
        this(seed, dataFolder, json, default1, default2, d -> d);
    }
    
    public DoubleRangeJsonLoader(@Nonnull final SeedString<K> seed, final Path dataFolder, final JsonElement json, final double default1, final double default2, final DoubleToDoubleFunction function) {
        super(seed.append(".DoubleRange"), dataFolder, json);
        this.default1 = default1;
        this.default2 = default2;
        this.function = Objects.requireNonNull(function);
    }
    
    @Override
    public IDoubleRange load() {
        if (this.json == null || this.json.isJsonNull()) {
            if (this.default1 == this.default2) {
                return new DoubleRange.Constant(this.function.get(this.default1));
            }
            return new DoubleRange.Normal(this.function.get(this.default1), this.function.get(this.default2));
        }
        else if (this.json.isJsonArray()) {
            final JsonArray array = this.json.getAsJsonArray();
            if (array.size() != 1 && array.size() != 2) {
                throw new IllegalStateException(String.format("Range array contains %s values. Only 1 or 2 entries are allowed.", array.size()));
            }
            if (array.size() == 1) {
                return new DoubleRange.Constant(this.function.get(array.get(0).getAsDouble()));
            }
            return new DoubleRange.Normal(this.function.get(array.get(0).getAsDouble()), this.function.get(array.get(1).getAsDouble()));
        }
        else {
            if (!this.json.isJsonObject()) {
                return new DoubleRange.Constant(this.function.get(this.json.getAsDouble()));
            }
            if (this.has("Thresholds") && this.has("Values")) {
                return this.loadThreshold();
            }
            if (!this.has("Min")) {
                throw new IllegalStateException("Minimum value of range is not defined. Keyword: Min");
            }
            if (!this.has("Max")) {
                throw new IllegalStateException("Maximum value of range is not defined. Keyword: Max");
            }
            final double min = this.get("Min").getAsDouble();
            final double max = this.get("Max").getAsDouble();
            return new DoubleRange.Normal(this.function.get(min), this.function.get(max));
        }
    }
    
    @Nonnull
    protected IDoubleRange loadThreshold() {
        final JsonArray thresholdsJson = this.get("Thresholds").getAsJsonArray();
        final JsonArray valuesJson = this.get("Values").getAsJsonArray();
        final double[] thresholds = new double[thresholdsJson.size()];
        final double[] values = new double[thresholdsJson.size()];
        for (int i = 0; i < thresholds.length; ++i) {
            thresholds[i] = thresholdsJson.get(i).getAsDouble();
            values[i] = valuesJson.get(i).getAsDouble();
        }
        return new DoubleRange.Multiple(thresholds, values);
    }
    
    public interface Constants
    {
        public static final String KEY_MIN = "Min";
        public static final String KEY_MAX = "Max";
        public static final String KEY_THRESHOLDS = "Thresholds";
        public static final String KEY_VALUES = "Values";
        public static final String ERROR_ARRAY_SIZE = "Range array contains %s values. Only 1 or 2 entries are allowed.";
        public static final String ERROR_NO_MIN = "Minimum value of range is not defined. Keyword: Min";
        public static final String ERROR_NO_MAX = "Maximum value of range is not defined. Keyword: Max";
    }
    
    @FunctionalInterface
    public interface DoubleToDoubleFunction
    {
        double get(final double p0);
    }
}
