package net.minecraft.world.level.pathfinder;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.entity.Entity;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import java.util.Set;
import java.util.List;

public class Path {
    private final List<Node> nodes;
    private Node[] openSet;
    private Node[] closedSet;
    private Set<Target> targetNodes;
    private int index;
    private final BlockPos target;
    private final float distToTarget;
    private final boolean reached;
    
    public Path(final List<Node> list, final BlockPos fu, final boolean boolean3) {
        this.openSet = new Node[0];
        this.closedSet = new Node[0];
        this.nodes = list;
        this.target = fu;
        this.distToTarget = (list.isEmpty() ? Float.MAX_VALUE : this.nodes.get(this.nodes.size() - 1).distanceManhattan(this.target));
        this.reached = boolean3;
    }
    
    public void next() {
        ++this.index;
    }
    
    public boolean isDone() {
        return this.index >= this.nodes.size();
    }
    
    @Nullable
    public Node last() {
        if (!this.nodes.isEmpty()) {
            return this.nodes.get(this.nodes.size() - 1);
        }
        return null;
    }
    
    public Node get(final int integer) {
        return this.nodes.get(integer);
    }
    
    public List<Node> getNodes() {
        return this.nodes;
    }
    
    public void truncate(final int integer) {
        if (this.nodes.size() > integer) {
            this.nodes.subList(integer, this.nodes.size()).clear();
        }
    }
    
    public void set(final int integer, final Node czd) {
        this.nodes.set(integer, czd);
    }
    
    public int getSize() {
        return this.nodes.size();
    }
    
    public int getIndex() {
        return this.index;
    }
    
    public void setIndex(final int integer) {
        this.index = integer;
    }
    
    public Vec3 getPos(final Entity aom, final int integer) {
        final Node czd4 = this.nodes.get(integer);
        final double double5 = czd4.x + (int)(aom.getBbWidth() + 1.0f) * 0.5;
        final double double6 = czd4.y;
        final double double7 = czd4.z + (int)(aom.getBbWidth() + 1.0f) * 0.5;
        return new Vec3(double5, double6, double7);
    }
    
    public Vec3 currentPos(final Entity aom) {
        return this.getPos(aom, this.index);
    }
    
    public Vec3i currentPos() {
        final Node czd2 = this.currentNode();
        return new Vec3i(czd2.x, czd2.y, czd2.z);
    }
    
    public Node currentNode() {
        return this.nodes.get(this.index);
    }
    
    public boolean sameAs(@Nullable final Path czf) {
        if (czf == null) {
            return false;
        }
        if (czf.nodes.size() != this.nodes.size()) {
            return false;
        }
        for (int integer3 = 0; integer3 < this.nodes.size(); ++integer3) {
            final Node czd4 = this.nodes.get(integer3);
            final Node czd5 = czf.nodes.get(integer3);
            if (czd4.x != czd5.x || czd4.y != czd5.y || czd4.z != czd5.z) {
                return false;
            }
        }
        return true;
    }
    
    public boolean canReach() {
        return this.reached;
    }
    
    public Node[] getOpenSet() {
        return this.openSet;
    }
    
    public Node[] getClosedSet() {
        return this.closedSet;
    }
    
    public static Path createFromStream(final FriendlyByteBuf mg) {
        final boolean boolean2 = mg.readBoolean();
        final int integer3 = mg.readInt();
        final int integer4 = mg.readInt();
        final Set<Target> set5 = Sets.newHashSet();
        for (int integer5 = 0; integer5 < integer4; ++integer5) {
            set5.add(Target.createFromStream(mg));
        }
        final BlockPos fu6 = new BlockPos(mg.readInt(), mg.readInt(), mg.readInt());
        final List<Node> list7 = Lists.newArrayList();
        for (int integer6 = mg.readInt(), integer7 = 0; integer7 < integer6; ++integer7) {
            list7.add(Node.createFromStream(mg));
        }
        final Node[] arr9 = new Node[mg.readInt()];
        for (int integer8 = 0; integer8 < arr9.length; ++integer8) {
            arr9[integer8] = Node.createFromStream(mg);
        }
        final Node[] arr10 = new Node[mg.readInt()];
        for (int integer9 = 0; integer9 < arr10.length; ++integer9) {
            arr10[integer9] = Node.createFromStream(mg);
        }
        final Path czf11 = new Path(list7, fu6, boolean2);
        czf11.openSet = arr9;
        czf11.closedSet = arr10;
        czf11.targetNodes = set5;
        czf11.index = integer3;
        return czf11;
    }
    
    @Override
    public String toString() {
        return "Path(length=" + this.nodes.size() + ")";
    }
    
    public BlockPos getTarget() {
        return this.target;
    }
    
    public float getDistToTarget() {
        return this.distToTarget;
    }
}
