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

package com.hypixel.hytale.builtin.hytalegenerator.framework.math;

import javax.annotation.Nonnull;

public class Combiner
{
    private final double y;
    private double value;
    
    public Combiner(final double background, final double y) {
        this.value = background;
        this.y = y;
    }
    
    @Nonnull
    public Layer addLayer(final double density) {
        return new Layer(this, density);
    }
    
    public double getValue() {
        return this.value;
    }
    
    public enum IntersectionPolicy
    {
        MAX_POLICY, 
        MIN_POLICY;
    }
    
    public class Layer
    {
        @Nonnull
        private final Combiner parent;
        private double value;
        private double floor;
        private double ceiling;
        private double paddingFloor;
        private double paddingCeiling;
        private IntersectionPolicy intersectionPolicy;
        private double intersectionSmoothingRange;
        private boolean withLimitsCheck;
        private boolean withPaddingCheck;
        private boolean withIntersectionPolicyCheck;
        private boolean isFinished;
        
        private Layer(final Combiner combiner, final double value) {
            this.isFinished = false;
            if (combiner == null) {
                throw new NullPointerException();
            }
            this.parent = combiner;
            this.value = value;
        }
        
        @Nonnull
        public Combiner finishLayer() {
            if (!this.withPaddingCheck || !this.withIntersectionPolicyCheck || !this.withLimitsCheck) {
                throw new IllegalStateException("incomplete");
            }
            if (this.isFinished) {
                throw new IllegalStateException("method was already called");
            }
            this.isFinished = true;
            if (this.intersectionPolicy == IntersectionPolicy.MAX_POLICY) {
                this.ceiling = Calculator.smoothMax(this.intersectionSmoothingRange, this.floor, this.ceiling);
            }
            else if (this.intersectionPolicy == IntersectionPolicy.MIN_POLICY) {
                this.floor = Calculator.smoothMin(this.intersectionSmoothingRange, this.floor, this.ceiling);
            }
            else {
                this.ceiling = this.floor;
            }
            if (Combiner.this.y < this.floor || Combiner.this.y >= this.ceiling) {
                return this.parent;
            }
            double floorPaddingMultiplier;
            if (this.paddingFloor == 0.0) {
                floorPaddingMultiplier = 1.0;
            }
            else {
                floorPaddingMultiplier = (Combiner.this.y - this.floor) / this.paddingFloor;
                floorPaddingMultiplier = Calculator.clamp(0.0, floorPaddingMultiplier, 1.0);
            }
            double ceilingPaddingMultiplier;
            if (this.paddingCeiling == 0.0) {
                ceilingPaddingMultiplier = 1.0;
            }
            else {
                ceilingPaddingMultiplier = (this.ceiling - Combiner.this.y) / this.paddingCeiling;
                ceilingPaddingMultiplier = Calculator.clamp(0.0, ceilingPaddingMultiplier, 1.0);
            }
            final double paddingMultiplier = Calculator.smoothMin(0.2, floorPaddingMultiplier, ceilingPaddingMultiplier);
            this.value *= paddingMultiplier;
            final Combiner parent = this.parent;
            parent.value += this.value;
            return this.parent;
        }
        
        @Nonnull
        public Layer withLimits(final double floor, final double ceiling) {
            this.withLimitsCheck = true;
            this.floor = floor;
            this.ceiling = ceiling;
            return this;
        }
        
        @Nonnull
        public Layer withPadding(final double paddingFloor, final double paddingCeiling) {
            if (paddingFloor < 0.0 || paddingCeiling < 0.0) {
                throw new IllegalArgumentException("negative padding values");
            }
            this.withPaddingCheck = true;
            this.paddingFloor = paddingFloor;
            this.paddingCeiling = paddingCeiling;
            return this;
        }
        
        @Nonnull
        public Layer withIntersectionPolicy(@Nonnull final IntersectionPolicy policy, final double smoothRange) {
            if (policy == null) {
                throw new NullPointerException();
            }
            this.withIntersectionPolicyCheck = true;
            this.intersectionPolicy = policy;
            this.intersectionSmoothingRange = smoothRange;
            return this;
        }
    }
}
