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

package com.hypixel.hytale.server.npc.instructions;

import com.hypixel.hytale.math.random.RandomExtra;
import java.util.concurrent.ThreadLocalRandom;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.npc.role.Role;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.common.map.WeightedMap;
import com.hypixel.hytale.server.npc.instructions.builders.BuilderInstruction;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import com.hypixel.hytale.server.npc.instructions.builders.BuilderInstructionRandomized;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import com.hypixel.hytale.common.map.IWeightedMap;

public class InstructionRandomized extends Instruction
{
    @Nonnull
    protected final IWeightedMap<InstructionHolder> weightedInstructionMap;
    protected final boolean resetOnStateChange;
    protected final double minExecuteTime;
    protected final double maxExecuteTime;
    protected double timeout;
    @Nullable
    protected InstructionHolder current;
    
    public InstructionRandomized(@Nonnull final BuilderInstructionRandomized builder, final Sensor sensor, @Nonnull final Instruction[] instructionList, @Nonnull final BuilderSupport support) {
        super(builder, sensor, instructionList, support);
        final WeightedMap.Builder<InstructionHolder> mapBuilder = WeightedMap.builder(InstructionHolder.EMPTY_ARRAY);
        for (final Instruction instruction : instructionList) {
            mapBuilder.put(new InstructionHolder(instruction), instruction.getWeight());
        }
        this.weightedInstructionMap = mapBuilder.build();
        this.resetOnStateChange = builder.getResetOnStateChange(support);
        final double[] executeTimeRange = builder.getExecuteFor(support);
        this.minExecuteTime = executeTimeRange[0];
        this.maxExecuteTime = executeTimeRange[1];
    }
    
    @Override
    public void execute(@Nonnull final Ref<EntityStore> ref, @Nonnull final Role role, final double dt, @Nonnull final Store<EntityStore> store) {
        if (this.instructionList.length == 0) {
            return;
        }
        this.timeout -= dt;
        if (this.timeout <= 0.0 || this.current == null) {
            final ThreadLocalRandom random = ThreadLocalRandom.current();
            this.current = this.weightedInstructionMap.get(random.nextDouble());
            this.timeout = RandomExtra.randomRange(this.minExecuteTime, this.maxExecuteTime);
        }
        final Instruction instruction = this.current.instruction;
        if (instruction.matches(ref, role, dt, store)) {
            instruction.onMatched(role);
            instruction.execute(ref, role, dt, store);
            instruction.onCompleted(role);
        }
    }
    
    @Override
    public void clearOnce() {
        super.clearOnce();
        if (this.resetOnStateChange) {
            this.current = null;
        }
    }
    
    @Override
    public void reset() {
        super.clearOnce();
        this.current = null;
    }
    
    protected static class InstructionHolder
    {
        protected static final InstructionHolder[] EMPTY_ARRAY;
        private final Instruction instruction;
        
        protected InstructionHolder(final Instruction instruction) {
            this.instruction = instruction;
        }
        
        static {
            EMPTY_ARRAY = new InstructionHolder[0];
        }
    }
}
