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

package com.hypixel.hytale.server.npc.statetransition.builders;

import javax.annotation.Nullable;
import java.util.Iterator;
import com.hypixel.hytale.server.npc.statetransition.StateTransitionController;
import java.util.BitSet;
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.validators.ArrayValidator;
import com.hypixel.hytale.server.npc.asset.builder.BuilderObjectArrayHelper;
import com.hypixel.hytale.server.npc.asset.builder.Builder;
import com.google.gson.JsonElement;
import com.hypixel.hytale.server.npc.util.expression.ExecutionContext;
import com.hypixel.hytale.server.npc.asset.builder.BuilderDescriptorState;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.npc.asset.builder.BuilderContext;
import com.hypixel.hytale.server.npc.asset.builder.holder.BooleanHolder;
import com.hypixel.hytale.server.npc.instructions.ActionList;
import com.hypixel.hytale.server.npc.asset.builder.BuilderObjectReferenceHelper;
import com.hypixel.hytale.server.npc.asset.builder.BuilderObjectStaticListHelper;
import com.hypixel.hytale.server.npc.asset.builder.BuilderBase;

public class BuilderStateTransition extends BuilderBase<StateTransition>
{
    protected final BuilderObjectStaticListHelper<BuilderStateTransitionEdges.StateTransitionEdges> stateTransitionEdges;
    protected final BuilderObjectReferenceHelper<ActionList> actions;
    protected final BooleanHolder enabled;
    
    public BuilderStateTransition() {
        this.stateTransitionEdges = new BuilderObjectStaticListHelper<BuilderStateTransitionEdges.StateTransitionEdges>(BuilderStateTransitionEdges.StateTransitionEdges.class, this);
        this.actions = new BuilderObjectReferenceHelper<ActionList>(ActionList.class, this);
        this.enabled = new BooleanHolder();
    }
    
    @Nonnull
    @Override
    public String getShortDescription() {
        return "An entry containing a list of actions to execute when moving from one state to another";
    }
    
    @Nonnull
    @Override
    public String getLongDescription() {
        return this.getShortDescription();
    }
    
    @Nonnull
    @Override
    public StateTransition build(@Nonnull final BuilderSupport builderSupport) {
        return new StateTransition(this, builderSupport);
    }
    
    @Nonnull
    @Override
    public Class<StateTransition> category() {
        return StateTransition.class;
    }
    
    @Nonnull
    @Override
    public BuilderDescriptorState getBuilderDescriptorState() {
        return BuilderDescriptorState.Stable;
    }
    
    @Override
    public boolean isEnabled(final ExecutionContext context) {
        return this.enabled.get(context);
    }
    
    @Nonnull
    @Override
    public Builder<StateTransition> readConfig(@Nonnull final JsonElement data) {
        this.requireArray(data, "States", this.stateTransitionEdges, null, BuilderDescriptorState.Stable, "List of state transitions", null, this.validationHelper);
        this.requireObject(data, "Actions", this.actions, BuilderDescriptorState.Stable, "List of actions", null, this.validationHelper);
        this.getBoolean(data, "Enabled", this.enabled, true, BuilderDescriptorState.Stable, "Whether this sensor should be enabled on the NPC", null);
        return this;
    }
    
    @Override
    public boolean validate(final String configName, @Nonnull final NPCLoadTimeValidationHelper validationHelper, @Nonnull final ExecutionContext context, final Scope globalScope, @Nonnull final List<String> errors) {
        boolean valid = super.validate(configName, validationHelper, context, globalScope, errors) & this.stateTransitionEdges.validate(configName, validationHelper, this.builderManager, context, globalScope, errors) & this.actions.validate(configName, validationHelper, this.builderManager, context, globalScope, errors);
        final List<BuilderStateTransitionEdges.StateTransitionEdges> edges = this.stateTransitionEdges.staticBuild(this.builderManager);
        final BitSet seenEdges = new BitSet();
        final int[] allMainStates = this.stateHelper.getAllMainStates();
        for (final BuilderStateTransitionEdges.StateTransitionEdges edge : edges) {
            for (final int from : (edge.getFromStateIndices() != null) ? edge.getFromStateIndices() : allMainStates) {
                for (final int to : (edge.getToStateIndices() != null) ? edge.getToStateIndices() : allMainStates) {
                    final int combinedValue = StateTransitionController.indexStateTransitionEdge(from, to);
                    if (seenEdges.get(combinedValue)) {
                        errors.add(String.format("Cannot define the same edge twice in state transitions: %s -> %s!", this.stateHelper.getStateName(from), this.stateHelper.getStateName(to)));
                        valid = false;
                    }
                    else {
                        seenEdges.set(combinedValue);
                    }
                }
            }
        }
        return valid;
    }
    
    @Nullable
    public List<BuilderStateTransitionEdges.StateTransitionEdges> getStateTransitionEdges(@Nonnull final BuilderSupport support) {
        return this.stateTransitionEdges.build(support);
    }
    
    @Nonnull
    public ActionList getActionList(@Nonnull final BuilderSupport builderSupport) {
        final ActionList actions = this.actions.build(builderSupport);
        if (actions != ActionList.EMPTY_ACTION_LIST) {
            actions.setAtomic(false);
            actions.setBlocking(true);
        }
        return actions;
    }
    
    public static class StateTransition
    {
        @Nullable
        private final List<BuilderStateTransitionEdges.StateTransitionEdges> stateTransitionEdges;
        @Nonnull
        private final ActionList actions;
        
        private StateTransition(@Nonnull final BuilderStateTransition builder, @Nonnull final BuilderSupport support) {
            this.stateTransitionEdges = builder.getStateTransitionEdges(support);
            this.actions = builder.getActionList(support);
        }
        
        @Nullable
        public List<BuilderStateTransitionEdges.StateTransitionEdges> getStateTransitionEdges() {
            return this.stateTransitionEdges;
        }
        
        @Nonnull
        public ActionList getActions() {
            return this.actions;
        }
    }
}
