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

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

import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.npc.entities.NPCEntity;
import com.hypixel.hytale.server.core.entity.group.EntityGroup;
import com.hypixel.hytale.server.flock.FlockPlugin;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.npc.movement.controllers.MotionController;
import com.hypixel.hytale.server.npc.util.NPCPhysicsMath;
import com.hypixel.hytale.component.ComponentAccessor;
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.server.npc.corecomponents.movement.builders.BuilderBodyMotionWanderBase;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionWanderInCircle;
import com.hypixel.hytale.math.vector.Vector3d;

public class BodyMotionWanderInCircle extends BodyMotionWanderBase
{
    protected final double radius;
    protected final boolean flock;
    protected final boolean useSphere;
    protected final Vector3d referencePoint;
    
    public BodyMotionWanderInCircle(@Nonnull final BuilderBodyMotionWanderInCircle builder, @Nonnull final BuilderSupport builderSupport) {
        super(builder, builderSupport);
        this.referencePoint = new Vector3d();
        this.radius = builder.getRadius(builderSupport);
        this.flock = builder.isFlock();
        this.useSphere = builder.isUseSphere();
    }
    
    @Override
    protected double constrainMove(@Nonnull final Ref<EntityStore> ref, @Nonnull final Role role, @Nonnull final Vector3d probePosition, @Nonnull final Vector3d targetPosition, final double moveDist, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        final Vector3d referencePoint = this.getReferencePoint(ref, componentAccessor);
        final double r2 = this.radius * this.radius;
        final MotionController activeMotionController = role.getActiveMotionController();
        if (this.useSphere) {
            final double endDist2 = activeMotionController.waypointDistanceSquared(targetPosition, referencePoint);
            if (endDist2 <= r2) {
                return moveDist;
            }
            final double startDist2 = activeMotionController.waypointDistanceSquared(probePosition, referencePoint);
            if (startDist2 >= r2) {
                return (endDist2 <= startDist2) ? moveDist : 0.0;
            }
            return NPCPhysicsMath.intersectLineSphereLerp(referencePoint, this.radius, probePosition, targetPosition, activeMotionController.getComponentSelector()) * moveDist;
        }
        else {
            final Vector3d n = activeMotionController.getWorldNormal();
            final double endDist3 = NPCPhysicsMath.squaredDistProjected(targetPosition.getX(), targetPosition.getY(), targetPosition.getZ(), referencePoint, n);
            if (endDist3 <= r2) {
                return moveDist;
            }
            final double startDist3 = NPCPhysicsMath.squaredDistProjected(probePosition.getX(), probePosition.getY(), probePosition.getZ(), referencePoint, n);
            if (startDist3 >= r2) {
                return (endDist3 <= startDist3) ? moveDist : 0.0;
            }
            return moveDist * Math.max(0.0, NPCPhysicsMath.rayCircleIntersect(probePosition, targetPosition, referencePoint, this.radius, n));
        }
    }
    
    protected Vector3d getReferencePoint(@Nonnull final Ref<EntityStore> ref, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (this.flock) {
            final World world = componentAccessor.getExternalData().getWorld();
            final TransformComponent entityTransformComponent = componentAccessor.getComponent(ref, TransformComponent.getComponentType());
            assert entityTransformComponent != null;
            final Vector3d entityPosition = entityTransformComponent.getPosition();
            final Ref<EntityStore> flockReference = FlockPlugin.getFlockReference(ref, componentAccessor);
            if (flockReference != null) {
                final EntityGroup entityGroupComponent = componentAccessor.getComponent(flockReference, EntityGroup.getComponentType());
                assert entityGroupComponent != null;
                final Ref<EntityStore> leaderRef = entityGroupComponent.getLeaderRef();
                if (leaderRef.isValid()) {
                    final TransformComponent leaderTransformComponent = componentAccessor.getComponent(leaderRef, TransformComponent.getComponentType());
                    assert leaderTransformComponent != null;
                    final Vector3d leaderPosition = leaderTransformComponent.getPosition();
                    this.referencePoint.assign(leaderPosition.getX(), leaderPosition.getY(), leaderPosition.getZ());
                    return this.referencePoint;
                }
            }
            this.referencePoint.assign(entityPosition);
            return this.referencePoint;
        }
        else {
            final NPCEntity npcComponent = componentAccessor.getComponent(ref, NPCEntity.getComponentType());
            assert npcComponent != null;
            return npcComponent.getLeashPoint();
        }
    }
}
