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

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

import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.npc.movement.controllers.MotionController;
import com.hypixel.hytale.server.npc.movement.controllers.MotionControllerFly;
import com.hypixel.hytale.server.npc.entities.NPCEntity;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.npc.movement.Steering;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider;
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.BuilderBodyMotionFind;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionLand;

public class BodyMotionLand extends BodyMotionFind
{
    protected final double goalLenience;
    protected final double goalLenienceSquared;
    
    public BodyMotionLand(@Nonnull final BuilderBodyMotionLand builderMotionLand, @Nonnull final BuilderSupport support) {
        super(builderMotionLand, support);
        this.goalLenience = builderMotionLand.getGoalLenience(support);
        this.goalLenienceSquared = this.goalLenience * this.goalLenience;
    }
    
    @Override
    public boolean computeSteering(@Nonnull final Ref<EntityStore> ref, @Nonnull final Role role, @Nullable final InfoProvider infoProvider, final double dt, @Nonnull final Steering desiredSteering, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        final boolean result = super.computeSteering(ref, role, infoProvider, dt, desiredSteering, componentAccessor);
        final TransformComponent transformComponent = componentAccessor.getComponent(ref, TransformComponent.getComponentType());
        assert transformComponent != null;
        if (!this.isGoalReached(ref, role.getActiveMotionController(), transformComponent.getPosition(), componentAccessor)) {
            return result;
        }
        final NPCEntity npcComponent = componentAccessor.getComponent(ref, NPCEntity.getComponentType());
        assert npcComponent != null;
        role.setActiveMotionController(ref, npcComponent, "Walk", componentAccessor);
        return false;
    }
    
    @Override
    public boolean canComputeMotion(@Nonnull final Ref<EntityStore> ref, @Nonnull final Role role, @Nullable final InfoProvider positionProvider, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        final MotionController activeMotionController = role.getActiveMotionController();
        return activeMotionController.matchesType(MotionControllerFly.class) && !activeMotionController.isObstructed() && super.canComputeMotion(ref, role, positionProvider, componentAccessor);
    }
    
    @Override
    protected boolean isGoalReached(@Nonnull final Ref<EntityStore> ref, @Nonnull final MotionController motionController, @Nonnull final Vector3d position, @Nonnull final Vector3d targetPosition, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        final double differenceY = targetPosition.y - position.y;
        if (differenceY < this.heightDifferenceMin || differenceY > this.heightDifferenceMax) {
            return false;
        }
        final double waypointDistanceSquared = motionController.waypointDistanceSquared(position, targetPosition);
        return (waypointDistanceSquared <= this.effectiveDistanceSquared || waypointDistanceSquared <= this.goalLenienceSquared) && (!this.reachable || this.canReachTarget(ref, motionController, position, targetPosition, componentAccessor));
    }
}
