package net.minecraft.core;

import java.util.Spliterators.AbstractSpliterator;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import net.minecraft.util.MathHelper;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkCoordIntPair;
import net.minecraft.world.level.chunk.IChunkAccess;

public class SectionPosition extends BaseBlockPosition {

    public static final int SECTION_BITS = 4;
    public static final int SECTION_SIZE = 16;
    private static final int SECTION_MASK = 15;
    public static final int SECTION_HALF_SIZE = 8;
    public static final int SECTION_MAX_INDEX = 15;
    private static final int PACKED_X_LENGTH = 22;
    private static final int PACKED_Y_LENGTH = 20;
    private static final int PACKED_Z_LENGTH = 22;
    private static final long PACKED_X_MASK = 4194303L;
    private static final long PACKED_Y_MASK = 1048575L;
    private static final long PACKED_Z_MASK = 4194303L;
    private static final int Y_OFFSET = 0;
    private static final int Z_OFFSET = 20;
    private static final int X_OFFSET = 42;
    private static final int RELATIVE_X_SHIFT = 8;
    private static final int RELATIVE_Y_SHIFT = 0;
    private static final int RELATIVE_Z_SHIFT = 4;

    SectionPosition(int i, int j, int k) {
        super(i, j, k);
    }

    public static SectionPosition a(int i, int j, int k) {
        return new SectionPosition(i, j, k);
    }

    public static SectionPosition a(BlockPosition blockposition) {
        return new SectionPosition(a(blockposition.getX()), a(blockposition.getY()), a(blockposition.getZ()));
    }

    public static SectionPosition a(ChunkCoordIntPair chunkcoordintpair, int i) {
        return new SectionPosition(chunkcoordintpair.x, i, chunkcoordintpair.z);
    }

    public static SectionPosition a(Entity entity) {
        return new SectionPosition(a(entity.cW()), a(entity.cY()), a(entity.dc()));
    }

    public static SectionPosition a(long i) {
        return new SectionPosition(b(i), c(i), d(i));
    }

    public static SectionPosition a(IChunkAccess ichunkaccess) {
        return a(ichunkaccess.getPos(), ichunkaccess.getMinSection());
    }

    public static long a(long i, EnumDirection enumdirection) {
        return a(i, enumdirection.getAdjacentX(), enumdirection.getAdjacentY(), enumdirection.getAdjacentZ());
    }

    public static long a(long i, int j, int k, int l) {
        return b(b(i) + j, c(i) + k, d(i) + l);
    }

    public static int a(double d0) {
        return a(MathHelper.floor(d0));
    }

    public static int a(int i) {
        return i >> 4;
    }

    public static int b(int i) {
        return i & 15;
    }

    public static short b(BlockPosition blockposition) {
        int i = b(blockposition.getX());
        int j = b(blockposition.getY());
        int k = b(blockposition.getZ());

        return (short) (i << 8 | k << 4 | j << 0);
    }

    public static int a(short short0) {
        return short0 >>> 8 & 15;
    }

    public static int b(short short0) {
        return short0 >>> 0 & 15;
    }

    public static int c(short short0) {
        return short0 >>> 4 & 15;
    }

    public int d(short short0) {
        return this.d() + a(short0);
    }

    public int e(short short0) {
        return this.e() + b(short0);
    }

    public int f(short short0) {
        return this.f() + c(short0);
    }

    public BlockPosition g(short short0) {
        return new BlockPosition(this.d(short0), this.e(short0), this.f(short0));
    }

    public static int c(int i) {
        return i << 4;
    }

    public static int a(int i, int j) {
        return c(i) + j;
    }

    public static int b(long i) {
        return (int) (i << 0 >> 42);
    }

    public static int c(long i) {
        return (int) (i << 44 >> 44);
    }

    public static int d(long i) {
        return (int) (i << 22 >> 42);
    }

    public int a() {
        return this.getX();
    }

    public int b() {
        return this.getY();
    }

    public int c() {
        return this.getZ();
    }

    public int d() {
        return c(this.a());
    }

    public int e() {
        return c(this.b());
    }

    public int f() {
        return c(this.c());
    }

    public int g() {
        return a(this.a(), 15);
    }

    public int h() {
        return a(this.b(), 15);
    }

    public int i() {
        return a(this.c(), 15);
    }

    public static long e(long i) {
        return b(a(BlockPosition.a(i)), a(BlockPosition.b(i)), a(BlockPosition.c(i)));
    }

    public static long f(long i) {
        return i & -1048576L;
    }

    public BlockPosition p() {
        return new BlockPosition(c(this.a()), c(this.b()), c(this.c()));
    }

    public BlockPosition q() {
        boolean flag = true;

        return this.p().c(8, 8, 8);
    }

    public ChunkCoordIntPair r() {
        return new ChunkCoordIntPair(this.a(), this.c());
    }

    public static long c(BlockPosition blockposition) {
        return b(a(blockposition.getX()), a(blockposition.getY()), a(blockposition.getZ()));
    }

    public static long b(int i, int j, int k) {
        long l = 0L;

        l |= ((long) i & 4194303L) << 42;
        l |= ((long) j & 1048575L) << 0;
        l |= ((long) k & 4194303L) << 20;
        return l;
    }

    public long s() {
        return b(this.a(), this.b(), this.c());
    }

    @Override
    public SectionPosition c(int i, int j, int k) {
        return i == 0 && j == 0 && k == 0 ? this : new SectionPosition(this.a() + i, this.b() + j, this.c() + k);
    }

    public Stream<BlockPosition> t() {
        return BlockPosition.a(this.d(), this.e(), this.f(), this.g(), this.h(), this.i());
    }

    public static Stream<SectionPosition> a(SectionPosition sectionposition, int i) {
        int j = sectionposition.a();
        int k = sectionposition.b();
        int l = sectionposition.c();

        return a(j - i, k - i, l - i, j + i, k + i, l + i);
    }

    public static Stream<SectionPosition> a(ChunkCoordIntPair chunkcoordintpair, int i, int j, int k) {
        int l = chunkcoordintpair.x;
        int i1 = chunkcoordintpair.z;

        return a(l - i, j, i1 - i, l + i, k - 1, i1 + i);
    }

    public static Stream<SectionPosition> a(final int i, final int j, final int k, final int l, final int i1, final int j1) {
        return StreamSupport.stream(new AbstractSpliterator<SectionPosition>((long) ((l - i + 1) * (i1 - j + 1) * (j1 - k + 1)), 64) {
            final CursorPosition cursor = new CursorPosition(i, j, k, l, i1, j1);

            public boolean tryAdvance(Consumer<? super SectionPosition> consumer) {
                if (this.cursor.a()) {
                    consumer.accept(new SectionPosition(this.cursor.b(), this.cursor.c(), this.cursor.d()));
                    return true;
                } else {
                    return false;
                }
            }
        }, false);
    }
}
