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

package com.hypixel.hytale.server.npc.corecomponents.combat.builders;

import com.hypixel.hytale.server.npc.asset.builder.Builder;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.npc.asset.builder.validators.DoubleRangeValidator;
import com.hypixel.hytale.server.npc.asset.builder.validators.DoubleArrayValidator;
import com.hypixel.hytale.server.npc.asset.builder.validators.DoubleSequenceValidator;
import com.hypixel.hytale.server.npc.asset.builder.validators.DoubleValidator;
import com.hypixel.hytale.server.npc.asset.builder.validators.DoubleSingleValidator;
import com.hypixel.hytale.server.npc.asset.builder.validators.asset.CombatInteractionValidator;
import com.hypixel.hytale.server.npc.asset.builder.validators.AssetValidator;
import com.google.gson.JsonElement;
import com.hypixel.hytale.server.npc.asset.builder.BuilderDescriptorState;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import com.hypixel.hytale.codec.validation.Validator;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.RootInteraction;
import java.util.Map;
import com.hypixel.hytale.server.npc.asset.builder.BuilderCodecObjectHelper;
import com.hypixel.hytale.server.npc.asset.builder.holder.DoubleHolder;
import com.hypixel.hytale.server.npc.asset.builder.holder.NumberArrayHolder;
import com.hypixel.hytale.server.npc.asset.builder.holder.FloatHolder;
import com.hypixel.hytale.server.npc.corecomponents.combat.ActionAttack;
import com.hypixel.hytale.server.npc.asset.builder.holder.EnumHolder;
import com.hypixel.hytale.server.npc.asset.builder.holder.AssetHolder;
import com.hypixel.hytale.server.npc.corecomponents.builders.BuilderActionBase;

public class BuilderActionAttack extends BuilderActionBase
{
    private static final String ATTACK_PARAMETER = "Attack";
    public static final String[] ANTECEDENT;
    public static final String[] SUBSEQUENT;
    public static final double[] DEFAULT_ATTACK_PAUSE_RANGE;
    public static final double[] DEFAULT_AIMING_TIME_RANGE;
    protected final AssetHolder attack;
    protected final EnumHolder<ActionAttack.AttackType> attackType;
    protected final FloatHolder chargeFor;
    protected final NumberArrayHolder attackPauseRange;
    protected final NumberArrayHolder aimingTimeRange;
    protected double meleeConeAngle;
    protected ActionAttack.BallisticMode ballisticMode;
    protected boolean checkLineOfSight;
    protected boolean avoidFriendlyFire;
    protected boolean damageFriendlies;
    protected boolean skipAiming;
    protected DoubleHolder chargeDistance;
    protected final BuilderCodecObjectHelper<Map<String, String>> interactionVars;
    protected boolean attackProvided;
    
    public BuilderActionAttack() {
        this.attack = new AssetHolder();
        this.attackType = new EnumHolder<ActionAttack.AttackType>();
        this.chargeFor = new FloatHolder();
        this.attackPauseRange = new NumberArrayHolder();
        this.aimingTimeRange = new NumberArrayHolder();
        this.ballisticMode = ActionAttack.BallisticMode.Short;
        this.chargeDistance = new DoubleHolder();
        this.interactionVars = new BuilderCodecObjectHelper<Map<String, String>>(RootInteraction.class, RootInteraction.CHILD_ASSET_CODEC_MAP, null);
    }
    
    @Nonnull
    @Override
    public ActionAttack build(@Nonnull final BuilderSupport builderSupport) {
        return new ActionAttack(this, builderSupport);
    }
    
    @Nonnull
    @Override
    public String getShortDescription() {
        return "Starts attack";
    }
    
    @Nonnull
    @Override
    public String getLongDescription() {
        return "Let NPC start an attack. When an attack is running no new attack is started.";
    }
    
    @Nonnull
    @Override
    public BuilderDescriptorState getBuilderDescriptorState() {
        return BuilderDescriptorState.Experimental;
    }
    
    @Nonnull
    @Override
    public BuilderActionAttack readConfig(@Nonnull final JsonElement data) {
        this.attackProvided = this.getAsset(data, "Attack", this.attack, null, CombatInteractionValidator.withConfig(AssetValidator.CanBeEmpty), BuilderDescriptorState.Experimental, "Attack pattern to use", "Attack pattern to use. If omitted, will cancel current attack");
        this.getEnum(data, "AttackType", this.attackType, ActionAttack.AttackType.class, ActionAttack.AttackType.Primary, BuilderDescriptorState.Stable, "The interaction type to use", null);
        this.getFloat(data, "ChargeFor", this.chargeFor, 0.0, DoubleSingleValidator.greaterEqual0(), BuilderDescriptorState.Stable, "How long to charge for", "How long to charge for. 0 indicates no charging. Also doubles as how long to block for");
        this.getDoubleRange(data, "AttackPauseRange", this.attackPauseRange, BuilderActionAttack.DEFAULT_ATTACK_PAUSE_RANGE, DoubleSequenceValidator.betweenWeaklyMonotonic(0.0, Double.MAX_VALUE), BuilderDescriptorState.Stable, "Range of minimum pause between attacks", null);
        this.getDoubleRange(data, "AimingTimeRange", this.aimingTimeRange, BuilderActionAttack.DEFAULT_AIMING_TIME_RANGE, DoubleSequenceValidator.betweenWeaklyMonotonic(0.0, Double.MAX_VALUE), BuilderDescriptorState.Stable, "A range from which to pick a random value denoting the max time the NPC will wait for aiming before launching the attack.", null);
        this.getBoolean(data, "LineOfSight", b -> this.checkLineOfSight = b, false, BuilderDescriptorState.Experimental, "Check Line of Sight before firing", null);
        this.getBoolean(data, "AvoidFriendlyFire", b -> this.avoidFriendlyFire = b, true, BuilderDescriptorState.Experimental, "Tries to avoid friendly fire if true", null);
        this.getEnum(data, "BallisticMode", e -> this.ballisticMode = e, ActionAttack.BallisticMode.class, ActionAttack.BallisticMode.Short, BuilderDescriptorState.WorkInProgress, "Trajectory to use", null);
        this.getDouble(data, "MeleeConeAngle", d -> this.meleeConeAngle = d, 30.0, DoubleRangeValidator.fromExclToIncl(0.0, 360.0), BuilderDescriptorState.WorkInProgress, "Cone angle considered for on target for melee", null);
        this.getBoolean(data, "DamageFriendlies", d -> this.damageFriendlies = d, false, BuilderDescriptorState.Stable, "Whether this attack should bypass ignored damage groups and deal damage to the target", null);
        this.getBoolean(data, "SkipAiming", b -> this.skipAiming = b, false, BuilderDescriptorState.Stable, "Whether aiming should be skipped an the attack just executed immediately.", null);
        this.getDouble(data, "ChargeDistance", this.chargeDistance, 0.0, DoubleSingleValidator.greaterEqual0(), BuilderDescriptorState.Stable, "If this is a charge attack, the distance required for the charge", null);
        this.getCodecObject(data, "InteractionVars", this.interactionVars, BuilderDescriptorState.Stable, "Set of interaction vars for modifying the interaction", null);
        this.validateBooleanImplicationAnyAntecedent(BuilderActionAttack.ANTECEDENT, new boolean[] { this.skipAiming }, true, BuilderActionAttack.SUBSEQUENT, new boolean[] { this.checkLineOfSight, this.avoidFriendlyFire }, false);
        return this;
    }
    
    @Nullable
    public String getAttack(@Nonnull final BuilderSupport builderSupport) {
        final String computedAttack = this.attack.get(builderSupport.getExecutionContext());
        return (computedAttack == null || computedAttack.isEmpty()) ? null : computedAttack;
    }
    
    public ActionAttack.AttackType getAttackType(@Nonnull final BuilderSupport support) {
        return this.attackType.get(support.getExecutionContext());
    }
    
    public float getChargeTime(@Nonnull final BuilderSupport support) {
        return this.chargeFor.get(support.getExecutionContext());
    }
    
    public double[] getAttackPauseRange(@Nonnull final BuilderSupport support) {
        return this.attackPauseRange.get(support.getExecutionContext());
    }
    
    public double[] getAimingTimeRange(@Nonnull final BuilderSupport support) {
        return this.aimingTimeRange.get(support.getExecutionContext());
    }
    
    public double getMeleeConeAngle() {
        return this.meleeConeAngle / 2.0 * 0.01745329238474369;
    }
    
    public ActionAttack.BallisticMode getBallisticMode() {
        return this.ballisticMode;
    }
    
    public boolean isCheckLineOfSight() {
        return this.checkLineOfSight;
    }
    
    public boolean isAvoidFriendlyFire() {
        return this.avoidFriendlyFire;
    }
    
    public boolean isDamageFriendlies() {
        return this.damageFriendlies;
    }
    
    public boolean isSkipAiming() {
        return this.skipAiming;
    }
    
    public double getChargeDistance(@Nonnull final BuilderSupport support) {
        return this.chargeDistance.get(support.getExecutionContext());
    }
    
    public int getAttackParameterSlot(@Nonnull final BuilderSupport support) {
        return this.attackProvided ? Integer.MIN_VALUE : support.getParameterSlot("Attack");
    }
    
    @Nullable
    public Map<String, String> getInteractionVars() {
        return this.interactionVars.build();
    }
    
    static {
        ANTECEDENT = new String[] { "SkipAiming" };
        SUBSEQUENT = new String[] { "LineOfSight", "AvoidFriendlyFire" };
        DEFAULT_ATTACK_PAUSE_RANGE = new double[] { 0.0, 0.0 };
        DEFAULT_AIMING_TIME_RANGE = new double[] { 0.0, 0.0 };
    }
}
