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

package com.hypixel.hytale.server.core.prefab;

import com.hypixel.hytale.server.core.universe.world.chunk.BlockRotationUtil;
import com.hypixel.hytale.math.Axis;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple;
import com.hypixel.hytale.math.vector.Vector3l;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.math.vector.Vector3d;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.Rotation;

public enum PrefabRotation
{
    ROTATION_0(Rotation.None, (RotationExecutor)new RotationExecutor_0()), 
    ROTATION_90(Rotation.Ninety, (RotationExecutor)new RotationExecutor_90()), 
    ROTATION_180(Rotation.OneEighty, (RotationExecutor)new RotationExecutor_180()), 
    ROTATION_270(Rotation.TwoSeventy, (RotationExecutor)new RotationExecutor_270());
    
    public static final PrefabRotation[] VALUES;
    public static final String PREFIX = "ROTATION_";
    private final Rotation rotation;
    private final RotationExecutor executor;
    
    @Nonnull
    public static PrefabRotation fromRotation(@Nonnull final Rotation rotation) {
        return switch (rotation) {
            default -> throw new MatchException(null, null);
            case None -> PrefabRotation.ROTATION_0;
            case Ninety -> PrefabRotation.ROTATION_90;
            case OneEighty -> PrefabRotation.ROTATION_180;
            case TwoSeventy -> PrefabRotation.ROTATION_270;
        };
    }
    
    @Nonnull
    public static PrefabRotation valueOfExtended(@Nonnull final String s) {
        if (s.startsWith("ROTATION_")) {
            return valueOf(s);
        }
        return valueOf("ROTATION_" + s);
    }
    
    private PrefabRotation(final Rotation rotation, final RotationExecutor executor) {
        this.rotation = rotation;
        this.executor = executor;
    }
    
    public PrefabRotation add(@Nonnull final PrefabRotation other) {
        final int val = this.rotation.getDegrees() + other.rotation.getDegrees();
        return PrefabRotation.VALUES[val % 360 / 90];
    }
    
    public void rotate(@Nonnull final Vector3d v) {
        final double x = v.x;
        final double z = v.z;
        v.x = this.executor.rotateDoubleX(x, z);
        v.z = this.executor.rotateDoubleZ(x, z);
    }
    
    public void rotate(@Nonnull final Vector3i v) {
        final int x = v.x;
        final int z = v.z;
        v.x = this.executor.rotateIntX(x, z);
        v.z = this.executor.rotateIntZ(x, z);
    }
    
    public void rotate(@Nonnull final Vector3l v) {
        final long x = v.x;
        final long z = v.z;
        v.x = this.executor.rotateLongX(x, z);
        v.z = this.executor.rotateLongZ(x, z);
    }
    
    public int getX(final int x, final int z) {
        return this.executor.rotateIntX(x, z);
    }
    
    public int getZ(final int x, final int z) {
        return this.executor.rotateIntZ(x, z);
    }
    
    public float getYaw() {
        return this.executor.getYaw();
    }
    
    public int getRotation(final int rotation) {
        if (this.rotation == Rotation.None) {
            return rotation;
        }
        final RotationTuple inRotation = RotationTuple.get(rotation);
        return RotationTuple.of(inRotation.yaw().add(this.rotation), inRotation.pitch(), inRotation.roll()).index();
    }
    
    public int getFiller(final int filler) {
        if (this.rotation == Rotation.None) {
            return filler;
        }
        return BlockRotationUtil.getRotatedFiller(filler, Axis.Y, this.rotation);
    }
    
    static {
        VALUES = values();
    }
    
    private static class RotationExecutor_0 implements RotationExecutor
    {
        @Override
        public float getYaw() {
            return 0.0f;
        }
        
        @Override
        public int rotateIntX(final int x, final int z) {
            return x;
        }
        
        @Override
        public long rotateLongX(final long x, final long z) {
            return x;
        }
        
        @Override
        public double rotateDoubleX(final double x, final double z) {
            return x;
        }
        
        @Override
        public int rotateIntZ(final int x, final int z) {
            return z;
        }
        
        @Override
        public long rotateLongZ(final long x, final long z) {
            return z;
        }
        
        @Override
        public double rotateDoubleZ(final double x, final double z) {
            return z;
        }
    }
    
    private static class RotationExecutor_90 implements RotationExecutor
    {
        @Override
        public float getYaw() {
            return -1.5707964f;
        }
        
        @Override
        public int rotateIntX(final int x, final int z) {
            return z;
        }
        
        @Override
        public long rotateLongX(final long x, final long z) {
            return z;
        }
        
        @Override
        public double rotateDoubleX(final double x, final double z) {
            return z;
        }
        
        @Override
        public int rotateIntZ(final int x, final int z) {
            return -x;
        }
        
        @Override
        public long rotateLongZ(final long x, final long z) {
            return -x;
        }
        
        @Override
        public double rotateDoubleZ(final double x, final double z) {
            return -x;
        }
    }
    
    private static class RotationExecutor_180 implements RotationExecutor
    {
        @Override
        public float getYaw() {
            return -3.1415927f;
        }
        
        @Override
        public int rotateIntX(final int x, final int z) {
            return -x;
        }
        
        @Override
        public long rotateLongX(final long x, final long z) {
            return -x;
        }
        
        @Override
        public double rotateDoubleX(final double x, final double z) {
            return -x;
        }
        
        @Override
        public int rotateIntZ(final int x, final int z) {
            return -z;
        }
        
        @Override
        public long rotateLongZ(final long x, final long z) {
            return -z;
        }
        
        @Override
        public double rotateDoubleZ(final double x, final double z) {
            return -z;
        }
    }
    
    private static class RotationExecutor_270 implements RotationExecutor
    {
        @Override
        public float getYaw() {
            return -4.712389f;
        }
        
        @Override
        public int rotateIntX(final int x, final int z) {
            return -z;
        }
        
        @Override
        public long rotateLongX(final long x, final long z) {
            return -z;
        }
        
        @Override
        public double rotateDoubleX(final double x, final double z) {
            return -z;
        }
        
        @Override
        public int rotateIntZ(final int x, final int z) {
            return x;
        }
        
        @Override
        public long rotateLongZ(final long x, final long z) {
            return x;
        }
        
        @Override
        public double rotateDoubleZ(final double x, final double z) {
            return x;
        }
    }
    
    private interface RotationExecutor
    {
        float getYaw();
        
        int rotateIntX(final int p0, final int p1);
        
        long rotateLongX(final long p0, final long p1);
        
        double rotateDoubleX(final double p0, final double p1);
        
        int rotateIntZ(final int p0, final int p1);
        
        long rotateLongZ(final long p0, final long p1);
        
        double rotateDoubleZ(final double p0, final double p1);
    }
}
