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

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

import java.util.Iterator;
import com.hypixel.hytale.math.vector.Transform;
import java.util.Set;
import java.util.List;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.component.Ref;
import java.util.ArrayList;
import com.hypixel.hytale.server.core.util.TargetUtil;
import com.hypixel.hytale.server.npc.entities.NPCEntity;
import com.hypixel.hytale.server.npc.NPCPlugin;
import com.hypixel.hytale.server.core.Message;
import java.util.HashSet;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.command.system.CommandContext;
import com.hypixel.hytale.server.core.command.system.arguments.types.ArgumentType;
import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes;
import com.hypixel.hytale.server.core.command.system.arguments.system.FlagArg;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.command.system.arguments.system.OptionalArg;

public abstract class NPCMultiSelectCommandBase extends NPCWorldCommandBase
{
    protected static final float DEFAULT_CONE_ANGLE = 30.0f;
    protected static final float DEFAULT_RANGE = 8.0f;
    protected static final float RANGE_MIN = 0.0f;
    protected static final float RANGE_MAX = 2048.0f;
    protected static final float CONE_ANGLE_MIN = 0.0f;
    protected static final float CONE_ANGLE_MAX = 180.0f;
    @Nonnull
    protected final OptionalArg<Float> coneAngleArg;
    @Nonnull
    protected final OptionalArg<Float> rangeArg;
    @Nonnull
    private final OptionalArg<String> rolesArg;
    @Nonnull
    private final FlagArg nearestArg;
    @Nonnull
    private final FlagArg presetCone30;
    @Nonnull
    private final FlagArg presetCone30all;
    @Nonnull
    private final FlagArg presetSphere;
    @Nonnull
    private final FlagArg presetRay;
    static final /* synthetic */ boolean $assertionsDisabled;
    
    public NPCMultiSelectCommandBase(@Nonnull final String name, @Nonnull final String description) {
        super(name, description);
        this.coneAngleArg = this.withOptionalArg("angle", "server.commands.npc.command.angle.desc", ArgTypes.FLOAT);
        this.rangeArg = this.withOptionalArg("range", "server.commands.npc.command.range.desc", ArgTypes.FLOAT);
        this.rolesArg = this.withOptionalArg("roles", "server.commands.npc.command.roles.desc", ArgTypes.STRING);
        this.nearestArg = this.withFlagArg("nearest", "server.commands.npc.command.nearest.desc");
        this.presetCone30 = this.withFlagArg("cone", "server.commands.npc.command.preset.cone.desc");
        this.presetCone30all = this.withFlagArg("coneAll", "server.commands.npc.command.preset.cone_all.desc");
        this.presetSphere = this.withFlagArg("sphere", "server.commands.npc.command.preset.sphere.desc");
        this.presetRay = this.withFlagArg("ray", "server.commands.npc.command.preset.ray.desc");
    }
    
    public NPCMultiSelectCommandBase(@Nonnull final String name, @Nonnull final String description, final boolean requiresConfirmation) {
        super(name, description, requiresConfirmation);
        this.coneAngleArg = this.withOptionalArg("angle", "server.commands.npc.command.angle.desc", ArgTypes.FLOAT);
        this.rangeArg = this.withOptionalArg("range", "server.commands.npc.command.range.desc", ArgTypes.FLOAT);
        this.rolesArg = this.withOptionalArg("roles", "server.commands.npc.command.roles.desc", ArgTypes.STRING);
        this.nearestArg = this.withFlagArg("nearest", "server.commands.npc.command.nearest.desc");
        this.presetCone30 = this.withFlagArg("cone", "server.commands.npc.command.preset.cone.desc");
        this.presetCone30all = this.withFlagArg("coneAll", "server.commands.npc.command.preset.cone_all.desc");
        this.presetSphere = this.withFlagArg("sphere", "server.commands.npc.command.preset.sphere.desc");
        this.presetRay = this.withFlagArg("ray", "server.commands.npc.command.preset.ray.desc");
    }
    
    public NPCMultiSelectCommandBase(@Nonnull final String description) {
        super(description);
        this.coneAngleArg = this.withOptionalArg("angle", "server.commands.npc.command.angle.desc", ArgTypes.FLOAT);
        this.rangeArg = this.withOptionalArg("range", "server.commands.npc.command.range.desc", ArgTypes.FLOAT);
        this.rolesArg = this.withOptionalArg("roles", "server.commands.npc.command.roles.desc", ArgTypes.STRING);
        this.nearestArg = this.withFlagArg("nearest", "server.commands.npc.command.nearest.desc");
        this.presetCone30 = this.withFlagArg("cone", "server.commands.npc.command.preset.cone.desc");
        this.presetCone30all = this.withFlagArg("coneAll", "server.commands.npc.command.preset.cone_all.desc");
        this.presetSphere = this.withFlagArg("sphere", "server.commands.npc.command.preset.sphere.desc");
        this.presetRay = this.withFlagArg("ray", "server.commands.npc.command.preset.ray.desc");
    }
    
    @Override
    protected void execute(@Nonnull final CommandContext context, @Nonnull final World world, @Nonnull final Store<EntityStore> store) {
        if (this.entityArg.provided(context)) {
            final Ref<EntityStore> ref = this.entityArg.get(store, context);
            if (ref == null) {
                return;
            }
            final NPCEntity npc = NPCWorldCommandBase.ensureIsNPC(context, store, ref);
            if (npc == null) {
                return;
            }
            this.execute(context, npc, world, store, ref);
        }
        else {
            Ref<EntityStore> playerRef = null;
            if (context.isPlayer()) {
                playerRef = context.senderAsPlayerRef();
            }
            if (playerRef == null || !playerRef.isValid()) {
                context.sendMessage(NPCMultiSelectCommandBase.MESSAGE_COMMANDS_ERRORS_PLAYER_OR_ARG);
                return;
            }
            final Set<String> roleSet = new HashSet<String>();
            if (this.rolesArg.provided(context)) {
                final String roleString = this.rolesArg.get(context);
                if (roleString == null || roleString.isEmpty()) {
                    context.sendMessage(Message.translation("server.commands.errors.npc.no_role_list_provided"));
                    return;
                }
                final String[] split;
                final String[] roles = split = roleString.split(",");
                for (final String role : split) {
                    if (!role.isBlank()) {
                        if (!NPCPlugin.get().hasRoleName(role)) {
                            context.sendMessage(Message.translation("server.commands.errors.npc.unknown_role").param("role", role));
                            return;
                        }
                        roleSet.add(role);
                    }
                }
            }
            final float range = this.rangeArg.provided(context) ? this.rangeArg.get(context) : 8.0f;
            if (range < 0.0f || range > 2048.0f) {
                context.sendMessage(Message.translation("server.commands.errors.validation.range.between_inclusive").param("param", "range").param("min", 0.0f).param("max", 2048.0f).param("value", range));
                return;
            }
            float coneAngleDeg;
            boolean nearest;
            if (this.presetCone30.provided(context)) {
                coneAngleDeg = 30.0f;
                nearest = true;
            }
            else if (this.presetCone30all.provided(context)) {
                coneAngleDeg = 30.0f;
                nearest = false;
            }
            else if (this.presetSphere.provided(context)) {
                coneAngleDeg = 180.0f;
                nearest = false;
            }
            else if (this.presetRay.provided(context)) {
                coneAngleDeg = 0.0f;
                nearest = true;
            }
            else {
                coneAngleDeg = (this.coneAngleArg.provided(context) ? ((float)this.coneAngleArg.get(context).intValue()) : 30.0f);
                if (coneAngleDeg < 0.0f || coneAngleDeg > 180.0f) {
                    context.sendMessage(Message.translation("server.commands.errors.validation.range.between_inclusive").param("param", "angle").param("min", 0.0f).param("max", 180.0f).param("value", coneAngleDeg));
                    return;
                }
                nearest = this.nearestArg.provided(context);
            }
            List<Ref<EntityStore>> refs = null;
            final ComponentType<EntityStore, NPCEntity> npcEntityComponentType = NPCEntity.getComponentType();
            assert npcEntityComponentType != null;
            Vector3d eyePosition;
            if (coneAngleDeg == 0.0f) {
                final Ref<EntityStore> ref2 = TargetUtil.getTargetEntity(playerRef, range, store);
                if (ref2 != null && store.getComponent(ref2, npcEntityComponentType) != null) {
                    refs = new ArrayList<Ref<EntityStore>>();
                    refs.add(ref2);
                }
                eyePosition = Vector3d.ZERO;
            }
            else {
                final TransformComponent playerTransform = store.getComponent(playerRef, TransformComponent.getComponentType());
                assert playerTransform != null;
                final Transform viewTransform = TargetUtil.getLook(playerRef, store);
                eyePosition = viewTransform.getPosition();
                final Vector3d eyeDirection = viewTransform.getDirection();
                assert eyePosition.length() == 1.0;
                refs = TargetUtil.getAllEntitiesInSphere(eyePosition, range, store);
                final float cosineConeAngle = (float)Math.cos((float)Math.toRadians(coneAngleDeg));
                assert cosineConeAngle == -1.0f;
                refs.removeIf(entityRef -> {
                    if (store.getComponent(entityRef, npcEntityComponentType) == null) {
                        return true;
                    }
                    else if (cosineConeAngle <= -1.0f) {
                        return false;
                    }
                    else {
                        final TransformComponent entityTransform = store.getComponent(entityRef, TransformComponent.getComponentType());
                        if (!NPCMultiSelectCommandBase.$assertionsDisabled && entityTransform == null) {
                            throw new AssertionError();
                        }
                        else {
                            final Vector3d direction = Vector3d.directionTo(eyePosition, entityTransform.getPosition());
                            final double lengthDirection = direction.length();
                            if (lengthDirection < 1.0E-4) {
                                return true;
                            }
                            else {
                                return eyeDirection.dot(direction) < cosineConeAngle * lengthDirection;
                            }
                        }
                    }
                });
            }
            if (refs != null && !refs.isEmpty() && !roleSet.isEmpty()) {
                final Ref<EntityStore> ref;
                refs.removeIf(ref -> {
                    final NPCEntity npc2 = store.getComponent(ref, npcEntityComponentType);
                    return !roleSet.contains(npc2.getRoleName());
                });
            }
            if (refs == null || refs.isEmpty()) {
                context.sendMessage(NPCMultiSelectCommandBase.MESSAGE_COMMANDS_ERRORS_NO_ENTITY_IN_VIEW);
                return;
            }
            if (nearest && refs.size() > 1) {
                Ref<EntityStore> nearestRef = refs.getFirst();
                double nearestDistanceSq = Double.MAX_VALUE;
                for (final Ref<EntityStore> ref3 : refs) {
                    final TransformComponent npcTransform = store.getComponent(ref3, TransformComponent.getComponentType());
                    assert npcTransform != null;
                    final double distanceSq = Vector3d.directionTo(eyePosition, npcTransform.getPosition()).squaredLength();
                    if (distanceSq >= nearestDistanceSq) {
                        continue;
                    }
                    nearestDistanceSq = distanceSq;
                    nearestRef = ref3;
                }
                refs = List.of(nearestRef);
            }
            this.processEntityList(context, world, store, refs);
        }
    }
    
    protected void processEntityList(@Nonnull final CommandContext context, @Nonnull final World world, @Nonnull final Store<EntityStore> store, @Nonnull final List<Ref<EntityStore>> refs) {
        refs.forEach(ref -> {
            final NPCEntity npc = store.getComponent(ref, NPCEntity.getComponentType());
            if (!NPCMultiSelectCommandBase.$assertionsDisabled && npc == null) {
                throw new AssertionError();
            }
            else {
                this.execute(context, npc, world, store, ref);
            }
        });
    }
}
