package net.minecraft.world.level.pathfinder;

import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;

public class Node {
    public final int x;
    public final int y;
    public final int z;
    private final int hash;
    public int heapIdx;
    public float g;
    public float h;
    public float f;
    public Node cameFrom;
    public boolean closed;
    public float walkedDistance;
    public float costMalus;
    public BlockPathTypes type;
    
    public Node(final int integer1, final int integer2, final int integer3) {
        this.heapIdx = -1;
        this.type = BlockPathTypes.BLOCKED;
        this.x = integer1;
        this.y = integer2;
        this.z = integer3;
        this.hash = createHash(integer1, integer2, integer3);
    }
    
    public Node cloneMove(final int integer1, final int integer2, final int integer3) {
        final Node czd5 = new Node(integer1, integer2, integer3);
        czd5.heapIdx = this.heapIdx;
        czd5.g = this.g;
        czd5.h = this.h;
        czd5.f = this.f;
        czd5.cameFrom = this.cameFrom;
        czd5.closed = this.closed;
        czd5.walkedDistance = this.walkedDistance;
        czd5.costMalus = this.costMalus;
        czd5.type = this.type;
        return czd5;
    }
    
    public static int createHash(final int integer1, final int integer2, final int integer3) {
        return (integer2 & 0xFF) | (integer1 & 0x7FFF) << 8 | (integer3 & 0x7FFF) << 24 | ((integer1 < 0) ? Integer.MIN_VALUE : 0) | ((integer3 < 0) ? 32768 : 0);
    }
    
    public float distanceTo(final Node czd) {
        final float float3 = (float)(czd.x - this.x);
        final float float4 = (float)(czd.y - this.y);
        final float float5 = (float)(czd.z - this.z);
        return Mth.sqrt(float3 * float3 + float4 * float4 + float5 * float5);
    }
    
    public float distanceToSqr(final Node czd) {
        final float float3 = (float)(czd.x - this.x);
        final float float4 = (float)(czd.y - this.y);
        final float float5 = (float)(czd.z - this.z);
        return float3 * float3 + float4 * float4 + float5 * float5;
    }
    
    public float distanceManhattan(final Node czd) {
        final float float3 = (float)Math.abs(czd.x - this.x);
        final float float4 = (float)Math.abs(czd.y - this.y);
        final float float5 = (float)Math.abs(czd.z - this.z);
        return float3 + float4 + float5;
    }
    
    public float distanceManhattan(final BlockPos fu) {
        final float float3 = (float)Math.abs(fu.getX() - this.x);
        final float float4 = (float)Math.abs(fu.getY() - this.y);
        final float float5 = (float)Math.abs(fu.getZ() - this.z);
        return float3 + float4 + float5;
    }
    
    public BlockPos asBlockPos() {
        return new BlockPos(this.x, this.y, this.z);
    }
    
    @Override
    public boolean equals(final Object object) {
        if (object instanceof Node) {
            final Node czd3 = (Node)object;
            return this.hash == czd3.hash && this.x == czd3.x && this.y == czd3.y && this.z == czd3.z;
        }
        return false;
    }
    
    @Override
    public int hashCode() {
        return this.hash;
    }
    
    public boolean inOpenSet() {
        return this.heapIdx >= 0;
    }
    
    @Override
    public String toString() {
        return "Node{x=" + this.x + ", y=" + this.y + ", z=" + this.z + '}';
    }
    
    public static Node createFromStream(final FriendlyByteBuf mg) {
        final Node czd2 = new Node(mg.readInt(), mg.readInt(), mg.readInt());
        czd2.walkedDistance = mg.readFloat();
        czd2.costMalus = mg.readFloat();
        czd2.closed = mg.readBoolean();
        czd2.type = BlockPathTypes.values()[mg.readInt()];
        czd2.f = mg.readFloat();
        return czd2;
    }
}
