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

package com.hypixel.hytale.server.npc.role.support;

import java.util.Objects;
import com.hypixel.hytale.server.core.modules.entitystats.EntityStatValue;
import com.hypixel.hytale.server.core.modules.entitystats.asset.DefaultEntityStatTypes;
import com.hypixel.hytale.server.core.entity.Entity;
import com.hypixel.hytale.server.core.modules.entitystats.EntityStatsModule;
import com.hypixel.hytale.server.npc.util.expression.Scope;
import com.hypixel.hytale.server.npc.util.expression.StdLib;
import com.hypixel.hytale.server.core.entity.nameplate.Nameplate;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.modules.entity.component.DisplayNameComponent;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.npc.role.builders.BuilderRole;
import com.hypixel.hytale.server.npc.util.IComponentExecutionControl;
import java.util.List;
import com.hypixel.hytale.server.npc.instructions.Instruction;
import com.hypixel.hytale.server.npc.util.expression.StdScope;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.npc.entities.NPCEntity;

public class EntitySupport
{
    protected final NPCEntity parent;
    @Nullable
    protected final String[] displayNames;
    @Nullable
    protected String nominatedDisplayName;
    protected StdScope sensorScope;
    @Nullable
    protected Instruction nextBodyMotionStep;
    @Nullable
    protected Instruction nextHeadMotionStep;
    protected final List<IComponentExecutionControl> delayingComponents;
    @Nullable
    protected List<String> targetPlayerActiveTasks;
    
    public EntitySupport(final NPCEntity parent, @Nonnull final BuilderRole builder) {
        this.delayingComponents = new ObjectArrayList<IComponentExecutionControl>();
        this.parent = parent;
        this.displayNames = builder.getDisplayNames();
    }
    
    public StdScope getSensorScope() {
        return this.sensorScope;
    }
    
    @Nullable
    public Instruction getNextBodyMotionStep() {
        return this.nextBodyMotionStep;
    }
    
    public boolean setNextBodyMotionStep(final Instruction step) {
        if (this.nextBodyMotionStep != null) {
            return false;
        }
        this.nextBodyMotionStep = step;
        return true;
    }
    
    public void clearNextBodyMotionStep() {
        this.nextBodyMotionStep = null;
    }
    
    @Nullable
    public Instruction getNextHeadMotionStep() {
        return this.nextHeadMotionStep;
    }
    
    public boolean setNextHeadMotionStep(final Instruction step) {
        if (this.nextHeadMotionStep != null) {
            return false;
        }
        this.nextHeadMotionStep = step;
        return true;
    }
    
    public void clearNextHeadMotionStep() {
        this.nextHeadMotionStep = null;
    }
    
    public void postRoleBuilt(@Nonnull final BuilderSupport builderSupport) {
        this.sensorScope = builderSupport.getSensorScope();
    }
    
    public void tick(final float dt) {
        int i = 0;
        while (i < this.delayingComponents.size()) {
            final IComponentExecutionControl component = this.delayingComponents.get(i);
            if (component.processDelay(dt)) {
                this.delayingComponents.remove(i);
            }
            else {
                ++i;
            }
        }
    }
    
    public void handleNominatedDisplayName(@Nonnull final Ref<EntityStore> ref, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (this.nominatedDisplayName != null) {
            setDisplayName(ref, this.nominatedDisplayName, componentAccessor);
        }
        this.nominatedDisplayName = null;
    }
    
    public void nominateDisplayName(@Nonnull final String displayName) {
        this.nominatedDisplayName = displayName;
    }
    
    public void pickRandomDisplayName(@Nonnull final Holder<EntityStore> holder, final boolean override) {
        if (this.displayNames == null || this.displayNames.length == 0) {
            return;
        }
        setDisplayName(holder, this.displayNames[MathUtil.randomInt(0, this.displayNames.length)], override);
    }
    
    public static void setDisplayName(@Nonnull final Holder<EntityStore> holder, @Nonnull final String displayName) {
        setDisplayName(holder, displayName, true);
    }
    
    public static void setDisplayName(@Nonnull final Holder<EntityStore> holder, @Nullable final String displayName, final boolean override) {
        final DisplayNameComponent displayNameComponent = holder.getComponent(DisplayNameComponent.getComponentType());
        if (displayNameComponent != null) {
            final Message displayNameMessage = displayNameComponent.getDisplayName();
            if (displayNameMessage != null && !displayNameMessage.getAnsiMessage().isEmpty() && !override) {
                return;
            }
        }
        holder.putComponent(DisplayNameComponent.getComponentType(), new DisplayNameComponent(Message.raw((displayName != null) ? displayName : "")));
        if (displayName != null) {
            final Nameplate nameplateComponent = holder.ensureAndGetComponent(Nameplate.getComponentType());
            nameplateComponent.setText(displayName);
        }
        else {
            holder.removeComponent(Nameplate.getComponentType());
        }
    }
    
    public void pickRandomDisplayName(@Nonnull final Ref<EntityStore> ref, final boolean override, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        setRandomDisplayName(ref, this.displayNames, override, componentAccessor);
    }
    
    public static void setRandomDisplayName(@Nonnull final Ref<EntityStore> ref, @Nullable final String[] names, final boolean override, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (names == null || names.length == 0) {
            return;
        }
        setDisplayName(ref, names[MathUtil.randomInt(0, names.length)], override, componentAccessor);
    }
    
    public static void setDisplayName(@Nonnull final Ref<EntityStore> ref, @Nonnull final String displayName, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        setDisplayName(ref, displayName, true, componentAccessor);
    }
    
    public static void setDisplayName(@Nonnull final Ref<EntityStore> ref, @Nullable final String displayName, final boolean override, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (!ref.isValid()) {
            return;
        }
        final DisplayNameComponent displayNameComponent = componentAccessor.getComponent(ref, DisplayNameComponent.getComponentType());
        if (displayNameComponent != null) {
            final Message displayNameMessage = displayNameComponent.getDisplayName();
            if (displayNameMessage != null && !displayNameMessage.getAnsiMessage().isEmpty() && !override) {
                return;
            }
        }
        componentAccessor.putComponent(ref, DisplayNameComponent.getComponentType(), new DisplayNameComponent(Message.raw((displayName != null) ? displayName : "")));
        if (displayName != null) {
            final Nameplate nameplateComponent = componentAccessor.ensureAndGetComponent(ref, Nameplate.getComponentType());
            nameplateComponent.setText(displayName);
        }
        else {
            componentAccessor.removeComponent(ref, Nameplate.getComponentType());
        }
    }
    
    public void addTargetPlayerActiveTask(@Nonnull final String task) {
        if (this.targetPlayerActiveTasks == null) {
            this.targetPlayerActiveTasks = new ObjectArrayList<String>();
        }
        this.targetPlayerActiveTasks.add(task);
    }
    
    public void clearTargetPlayerActiveTasks() {
        if (this.targetPlayerActiveTasks != null) {
            this.targetPlayerActiveTasks.clear();
        }
    }
    
    @Nullable
    public List<String> getTargetPlayerActiveTasks() {
        return this.targetPlayerActiveTasks;
    }
    
    public void registerDelay(@Nonnull final IComponentExecutionControl component) {
        this.delayingComponents.add(component);
    }
    
    @Nonnull
    public static StdScope createScope(@Nonnull final NPCEntity entity) {
        final StdScope scope = new StdScope(StdLib.getInstance());
        scope.addSupplier("blocked", () -> entity.getRole().getActiveMotionController().isObstructed());
        scope.addSupplier("health", () -> {
            final EntityStatValue healthStat = EntityStatsModule.get(entity).get(DefaultEntityStatTypes.getHealth());
            return (double)Objects.requireNonNull(healthStat).asPercentage();
        });
        return scope;
    }
}
