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

package com.hypixel.hytale.server.npc.movement.controllers.builders;

import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import java.util.List;
import com.hypixel.hytale.server.npc.util.expression.Scope;
import com.hypixel.hytale.server.npc.validators.NPCLoadTimeValidationHelper;
import com.hypixel.hytale.server.npc.asset.builder.BuilderInfo;
import java.util.Objects;
import com.hypixel.hytale.server.npc.NPCPlugin;
import com.hypixel.hytale.server.npc.util.expression.ExecutionContext;
import com.hypixel.hytale.server.npc.asset.builder.validators.DoubleRangeValidator;
import com.hypixel.hytale.server.npc.asset.builder.validators.DoubleValidator;
import com.hypixel.hytale.server.npc.asset.builder.BuilderDescriptorState;
import com.hypixel.hytale.server.npc.asset.builder.validators.DoubleSingleValidator;
import com.hypixel.hytale.server.npc.asset.builder.Builder;
import javax.annotation.Nonnull;
import com.google.gson.JsonElement;
import com.hypixel.hytale.server.npc.asset.builder.holder.FloatHolder;
import com.hypixel.hytale.server.npc.asset.builder.holder.DoubleHolder;
import com.hypixel.hytale.server.npc.movement.controllers.MotionController;
import com.hypixel.hytale.server.npc.asset.builder.BuilderBaseWithType;

public abstract class BuilderMotionControllerBase extends BuilderBaseWithType<MotionController>
{
    protected float epsilonAngle;
    protected double epsilonSpeed;
    protected double forceVelocityDamping;
    protected final DoubleHolder maxHorizontalSpeed;
    protected final DoubleHolder fastHorizontalThreshold;
    protected double fastHorizontalThresholdRange;
    protected final FloatHolder maxHeadRotationSpeed;
    
    public BuilderMotionControllerBase() {
        this.maxHorizontalSpeed = new DoubleHolder();
        this.fastHorizontalThreshold = new DoubleHolder();
        this.maxHeadRotationSpeed = new FloatHolder();
    }
    
    @Nonnull
    @Override
    public Builder<MotionController> readCommonConfig(@Nonnull final JsonElement data) {
        super.readCommonConfig(data);
        this.readTypeKey(data);
        this.getDouble(data, "EpsilonSpeed", v -> this.epsilonSpeed = v, 1.0E-5, DoubleSingleValidator.greater0(), BuilderDescriptorState.Experimental, "Minimum speed considered non 0", null);
        this.getFloat(data, "EpsilonAngle", v -> this.epsilonAngle = v, 3.0f, DoubleSingleValidator.greater0(), BuilderDescriptorState.Experimental, "Minimum angle difference considered non 0 in degrees", null);
        this.getFloat(data, "MaxHeadRotationSpeed", this.maxHeadRotationSpeed, 360.0, DoubleRangeValidator.between(0.0, 360.0), BuilderDescriptorState.Stable, "Maximum rotation speed of the head in degrees", null);
        this.getDouble(data, "ForceVelocityDamping", v -> this.forceVelocityDamping = v, 0.5, DoubleSingleValidator.greater0(), BuilderDescriptorState.Experimental, "Damping of external force/velocity over time", null);
        this.getDouble(data, "RunThreshold", this.fastHorizontalThreshold, 0.7, DoubleRangeValidator.between01(), BuilderDescriptorState.WorkInProgress, "Relative threshold when running animation should be used", null);
        this.getDouble(data, "RunThresholdRange", v -> this.fastHorizontalThresholdRange = v, 0.15, DoubleRangeValidator.between01(), BuilderDescriptorState.WorkInProgress, "Relative threshold range for switching between running/walking", null);
        return this;
    }
    
    @Override
    public final boolean isEnabled(final ExecutionContext context) {
        return true;
    }
    
    @Nonnull
    @Override
    public String getIdentifier() {
        final BuilderInfo builderInfo = NPCPlugin.get().getBuilderInfo(this);
        Objects.requireNonNull(builderInfo, "Have builder but can't get builderInfo for it");
        return builderInfo.getKeyName();
    }
    
    @Override
    public boolean validate(final String configName, @Nonnull final NPCLoadTimeValidationHelper validationHelper, final ExecutionContext context, final Scope globalScope, @Nonnull final List<String> errors) {
        final boolean result = super.validate(configName, validationHelper, context, globalScope, errors);
        validationHelper.registerMotionControllerType(this.getClassType());
        return result;
    }
    
    public float getEpsilonAngle() {
        return 0.017453292f * this.epsilonAngle;
    }
    
    public double getEpsilonSpeed() {
        return this.epsilonSpeed;
    }
    
    public double getForceVelocityDamping() {
        return this.forceVelocityDamping;
    }
    
    public double getMaxHorizontalSpeed(@Nonnull final BuilderSupport builderSupport) {
        return this.maxHorizontalSpeed.get(builderSupport.getExecutionContext());
    }
    
    public float getMaxHeadRotationSpeed(@Nonnull final BuilderSupport support) {
        return this.maxHeadRotationSpeed.get(support.getExecutionContext()) * 0.017453292f;
    }
    
    public double getFastHorizontalThreshold(@Nonnull final BuilderSupport builderSupport) {
        return this.fastHorizontalThreshold.get(builderSupport.getExecutionContext());
    }
    
    public double getFastHorizontalThresholdRange() {
        return this.fastHorizontalThresholdRange;
    }
    
    public abstract Class<? extends MotionController> getClassType();
}
