package com.straice.smoothdoors.client.anim;

import net.minecraft.block.BlockState;
import net.minecraft.block.DoorBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.enums.DoorHinge;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.world.BlockRenderView;

final class DoorAnimation {

    private DoorAnimation() {}

    static void apply(BlockState state, float angleDeg, MatrixStack matrices, BlockRenderView world) {
        if (world == null) return;

        Direction facing = state.get(DoorBlock.FACING);
        DoorHinge hinge = state.get(DoorBlock.HINGE);

        Direction hingeSide = (hinge == DoorHinge.RIGHT)
                ? facing.rotateYClockwise()
                : facing.rotateYCounterclockwise();

        Box bb = state.getOutlineShape(world, BlockPos.ORIGIN, ShapeContext.absent()).getBoundingBox();

        float cx = (float) ((bb.minX + bb.maxX) * 0.5);
        float cz = (float) ((bb.minZ + bb.maxZ) * 0.5);

        float pivotX = cx;
        float pivotZ = cz;

        switch (hingeSide) {
            case EAST -> pivotX = (float) bb.maxX;
            case WEST -> pivotX = (float) bb.minX;
            case SOUTH -> pivotZ = (float) bb.maxZ;
            case NORTH -> pivotZ = (float) bb.minZ;
            default -> {
                pivotX = cx;
                pivotZ = cz;
            }
        }

        float thickness = (facing == Direction.NORTH || facing == Direction.SOUTH)
                ? (float) (bb.maxZ - bb.minZ)
                : (float) (bb.maxX - bb.minX);
        float halfT = thickness * 0.5f;

        float dX = 0.0f;
        float dZ = 0.0f;
        switch (facing) {
            case NORTH -> dZ = halfT;
            case SOUTH -> dZ = -halfT;
            case WEST -> dX = halfT;
            case EAST -> dX = -halfT;
            default -> {
                dX = 0.0f;
                dZ = 0.0f;
            }
        }

        double rad = Math.toRadians(angleDeg);
        float cos = (float) Math.cos(rad);
        float sin = (float) Math.sin(rad);
        float rotDX = dX * cos - dZ * sin;
        float rotDZ = dX * sin + dZ * cos;
        float shiftX = dX - rotDX;
        float shiftZ = dZ - rotDZ;

        matrices.translate(shiftX, 0.0f, shiftZ);
        matrices.translate(pivotX, 0.0f, pivotZ);
        matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(angleDeg));
        matrices.translate(-pivotX, 0.0f, -pivotZ);
    }
}
