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

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

import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.codec.validation.Validator;
import com.hypixel.hytale.codec.validation.Validators;
import com.hypixel.hytale.server.core.command.system.arguments.system.OptionalArg;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.core.Message;
import java.util.ArrayDeque;
import com.hypixel.hytale.server.core.universe.world.path.IPath;
import com.hypixel.hytale.builtin.path.waypoint.RelativeWaypointDefinition;
import java.util.Queue;
import com.hypixel.hytale.builtin.path.path.TransientPath;
import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.component.Ref;
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.npc.entities.NPCEntity;
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 javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg;
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractCommandCollection;

public class NPCPathCommand extends AbstractCommandCollection
{
    public NPCPathCommand() {
        super("path", "server.commands.npc.path.desc");
        this.addSubCommand(new SetPathCommand());
        this.addSubCommand(new PolygonPathCommand());
    }
    
    public static class SetPathCommand extends NPCWorldCommandBase
    {
        @Nonnull
        private final RequiredArg<String> instructionsArg;
        
        public SetPathCommand() {
            super("", "server.commands.npc.path.desc");
            this.instructionsArg = this.withRequiredArg("instructions", "server.commands.npc.path.instructions.desc", ArgTypes.STRING);
        }
        
        @Override
        protected void execute(@Nonnull final CommandContext context, @Nonnull final NPCEntity npc, @Nonnull final World world, @Nonnull final Store<EntityStore> store, @Nonnull final Ref<EntityStore> ref) {
            final TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType());
            assert transformComponent != null;
            final HeadRotation headRotationComponent = store.getComponent(ref, HeadRotation.getComponentType());
            assert headRotationComponent != null;
            final String instructionsString = this.instructionsArg.get(context);
            final ArrayDeque<RelativeWaypointDefinition> instructions = this.parseInstructions(context, instructionsString);
            if (instructions == null) {
                return;
            }
            npc.getPathManager().setTransientPath(TransientPath.buildPath(transformComponent.getPosition(), headRotationComponent.getRotation(), instructions, 1.0));
        }
        
        @Nullable
        private ArrayDeque<RelativeWaypointDefinition> parseInstructions(@Nonnull final CommandContext context, @Nonnull final String str) {
            final ArrayDeque<RelativeWaypointDefinition> instructions = new ArrayDeque<RelativeWaypointDefinition>();
            final String[] parts = str.split(",");
            int index = 0;
            try {
                while (index < parts.length) {
                    final float rotation = Float.parseFloat(parts[index++]) * 0.017453292f;
                    final double distance = Double.parseDouble(parts[index++]);
                    instructions.add(new RelativeWaypointDefinition(rotation, distance));
                }
            }
            catch (final NumberFormatException e) {
                context.sendMessage(Message.raw("Invalid number format: " + e.getMessage()));
                return null;
            }
            catch (final IndexOutOfBoundsException e2) {
                context.sendMessage(Message.raw("Instructions must be defined in pairs! Missing distance value."));
                return null;
            }
            return instructions;
        }
    }
    
    public static class PolygonPathCommand extends NPCWorldCommandBase
    {
        @Nonnull
        private final RequiredArg<Integer> sidesArg;
        @Nonnull
        private final OptionalArg<Double> lengthArg;
        
        public PolygonPathCommand() {
            super("polygon", "server.commands.npc.path.polygon.desc");
            this.sidesArg = this.withRequiredArg("sides", "server.commands.npc.path.polygon.sides.desc", ArgTypes.INTEGER).addValidator((Validator<Integer>)Validators.greaterThan((DataType)0));
            this.lengthArg = this.withOptionalArg("length", "server.commands.npc.path.length.desc", ArgTypes.DOUBLE).addValidator((Validator<Double>)Validators.greaterThan((DataType)0.0));
        }
        
        @Override
        protected void execute(@Nonnull final CommandContext context, @Nonnull final NPCEntity npc, @Nonnull final World world, @Nonnull final Store<EntityStore> store, @Nonnull final Ref<EntityStore> ref) {
            final ArrayDeque<RelativeWaypointDefinition> instructions = new ArrayDeque<RelativeWaypointDefinition>();
            final Integer sides = this.sidesArg.get(context);
            final float angle = 6.2831855f / sides;
            final double length = this.lengthArg.provided(context) ? this.lengthArg.get(context) : 5.0;
            for (int i = 0; i < sides; ++i) {
                instructions.add(new RelativeWaypointDefinition(angle, length));
            }
            final TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType());
            assert transformComponent != null;
            final HeadRotation headRotationComponent = store.getComponent(ref, HeadRotation.getComponentType());
            assert headRotationComponent != null;
            final Vector3d position = transformComponent.getPosition();
            final Vector3f headRotation = headRotationComponent.getRotation();
            npc.getPathManager().setTransientPath(TransientPath.buildPath(position, headRotation, instructions, 1.0));
        }
    }
}
