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

package com.hypixel.hytale.server.npc.corecomponents.world;

import java.util.function.Supplier;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.npc.role.support.MarkedEntitySupport;
import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.npc.role.Role;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.npc.corecomponents.builders.BuilderSensorBase;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorEvent;
import com.hypixel.hytale.server.npc.sensorinfo.EntityPositionProvider;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.npc.corecomponents.SensorBase;

public abstract class SensorEvent extends SensorBase
{
    protected static final ComponentType<EntityStore, TransformComponent> TRANSFORM_COMPONENT_TYPE;
    protected final double range;
    protected final EventSearchType searchType;
    protected final int lockOnTargetSlot;
    protected int playerEventMessageSlot;
    protected int npcEventMessageSlot;
    protected final EntityPositionProvider positionProvider;
    
    public SensorEvent(@Nonnull final BuilderSensorEvent builder, @Nonnull final BuilderSupport support) {
        super(builder);
        this.positionProvider = new EntityPositionProvider();
        this.range = builder.getRange(support);
        this.searchType = builder.getEventSearchType(support);
        this.lockOnTargetSlot = builder.getLockOnTargetSlot(support);
    }
    
    @Override
    public boolean matches(@Nonnull final Ref<EntityStore> ref, @Nonnull final Role role, final double dt, @Nonnull final Store<EntityStore> store) {
        if (!super.matches(ref, role, dt, store)) {
            this.positionProvider.clear();
            return false;
        }
        switch (this.searchType.ordinal()) {
            case 0: {
                Ref<EntityStore> playerFirstTarget = this.getPlayerTarget(ref, store);
                if (playerFirstTarget == null) {
                    playerFirstTarget = this.getNpcTarget(ref, store);
                }
                return this.setTarget(role.getMarkedEntitySupport(), playerFirstTarget, store);
            }
            case 1: {
                return this.setTarget(role.getMarkedEntitySupport(), this.getPlayerTarget(ref, store), store);
            }
            case 2: {
                Ref<EntityStore> npcFirstTarget = this.getNpcTarget(ref, store);
                if (npcFirstTarget == null) {
                    npcFirstTarget = this.getPlayerTarget(ref, store);
                }
                return this.setTarget(role.getMarkedEntitySupport(), npcFirstTarget, store);
            }
            case 3: {
                return this.setTarget(role.getMarkedEntitySupport(), this.getNpcTarget(ref, store), store);
            }
            default: {
                return false;
            }
        }
    }
    
    @Override
    public InfoProvider getSensorInfo() {
        return this.positionProvider;
    }
    
    protected boolean setTarget(@Nonnull final MarkedEntitySupport support, @Nullable final Ref<EntityStore> target, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (target == null) {
            this.positionProvider.clear();
            return false;
        }
        final Ref<EntityStore> set = this.positionProvider.setTarget(target, componentAccessor);
        if (set == null) {
            return false;
        }
        if (this.lockOnTargetSlot >= 0) {
            support.setMarkedEntity(this.lockOnTargetSlot, set);
        }
        return true;
    }
    
    @Nullable
    protected abstract Ref<EntityStore> getPlayerTarget(@Nonnull final Ref<EntityStore> p0, @Nonnull final Store<EntityStore> p1);
    
    @Nullable
    protected abstract Ref<EntityStore> getNpcTarget(@Nonnull final Ref<EntityStore> p0, @Nonnull final Store<EntityStore> p1);
    
    static {
        TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType();
    }
    
    public enum EventSearchType implements Supplier<String>
    {
        PlayerFirst("search for events triggered by players first"), 
        PlayerOnly("search only for events triggered by players"), 
        NpcFirst("search for events triggered by npcs first"), 
        NpcOnly("search only for events triggered by npcs");
        
        private final String description;
        
        private EventSearchType(final String description) {
            this.description = description;
        }
        
        @Override
        public String get() {
            return this.description;
        }
    }
}
