package com.trunksbomb.minetriad.client.render;

import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import com.trunksbomb.minetriad.blockentity.DuelTableBlockEntity;
import com.trunksbomb.minetriad.game.BoardCell;
import com.trunksbomb.minetriad.game.BoardLocalSpace;
import com.trunksbomb.minetriad.world.DuelTableBlock;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.world.item.ItemStack;

public class DuelTableBlockEntityRenderer implements BlockEntityRenderer<DuelTableBlockEntity> {
    private static final float TABLE_CARD_Y = 1.066F;
    private static final float IDLE_BOB_HEIGHT = 0.012F;
    private static final float IDLE_BOB_SPEED = 0.08F;

    public DuelTableBlockEntityRenderer(BlockEntityRendererProvider.Context context) {
    }

    @Override
    public void render(DuelTableBlockEntity blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay) {
        for (int slot = 0; slot < DuelTableBlockEntity.SLOT_COUNT; slot++) {
            ItemStack stack = blockEntity.getCard(slot);
            if (stack.isEmpty()) {
                continue;
            }

            BoardCell cell = new BoardCell(slot / BoardCell.SIZE, slot % BoardCell.SIZE);
            BoardLocalSpace.SlotCenter center = BoardLocalSpace.slotCenter(cell, blockEntity.getBlockState().getValue(DuelTableBlock.FACING));
            float y = TABLE_CARD_Y;
            float extraFlip = 0.0F;
            boolean hideCard = false;
            float idleOffset = idleBob(blockEntity, slot, partialTick);
            if (blockEntity.isAnimatingSlot(slot)) {
                float progress = blockEntity.animationProgress(partialTick);
                if (blockEntity.isPlacementAnimation()) {
                    y += (1.0F - progress) * 0.18F;
                } else if (blockEntity.isCaptureAnimation()) {
                    y += idleOffset;
                    y += (float) Math.sin(progress * Math.PI) * 0.08F;
                    extraFlip = 360.0F * progress;
                }
            } else if (!blockEntity.hasActiveAnimation()) {
                y += idleOffset;
            }
            if (blockEntity.hasOverviewSweepAnimation()) {
                float progress = blockEntity.overviewSweepSlotProgress(slot, partialTick);
                y += (float) Math.sin(progress * Math.PI) * 0.05F;
            }
            if (blockEntity.hasClearWaveAnimation()) {
                float progress = blockEntity.clearWaveSlotProgress(slot, partialTick);
                y += progress * 0.22F;
                hideCard = progress >= 1.0F;
            }
            if (hideCard) {
                continue;
            }

            poseStack.pushPose();
            poseStack.translate(center.x(), y, center.z());
            poseStack.mulPose(Axis.YP.rotationDegrees(BoardLocalSpace.cardYawDegrees(blockEntity.getBlockState().getValue(DuelTableBlock.FACING))));
            if (extraFlip != 0.0F) {
                poseStack.mulPose(Axis.ZP.rotationDegrees(extraFlip));
            }
            poseStack.mulPose(Axis.XN.rotationDegrees(90.0F));
            poseStack.scale(0.24F, 0.24F, 0.24F);
            TriadCardItemRenderer.renderCard(stack, poseStack, buffer, perspectivePalette(blockEntity, blockEntity.ownerAt(slot)));
            poseStack.popPose();
        }
    }

    private static float idleBob(DuelTableBlockEntity blockEntity, int slot, float partialTick) {
        int age = blockEntity.slotAge(slot);
        int delay = 6 + deterministicOffset(blockEntity, slot) % 18;
        if (age <= delay) {
            return 0.0F;
        }

        float bobTime = (age - delay) + partialTick;
        return (float) Math.sin(bobTime * IDLE_BOB_SPEED) * IDLE_BOB_HEIGHT;
    }

    private static int deterministicOffset(DuelTableBlockEntity blockEntity, int slot) {
        return Math.floorMod(blockEntity.getBlockPos().hashCode() * 31 + slot * 17, 97);
    }

    private static TriadCardItemRenderer.CardPalette perspectivePalette(DuelTableBlockEntity blockEntity, int owner) {
        if (owner == DuelTableBlockEntity.OWNER_NONE || Minecraft.getInstance().player == null) {
            return new TriadCardItemRenderer.CardPalette(
                    new float[] {0.88F, 0.84F, 0.72F},
                    new float[] {0.20F, 0.22F, 0.28F});
        }

        var playerId = Minecraft.getInstance().player.getUUID();
        boolean ownerIsLocal = owner == DuelTableBlockEntity.OWNER_FIRST
                ? blockEntity.firstParticipantId().map(playerId::equals).orElse(false)
                : owner == DuelTableBlockEntity.OWNER_SECOND && blockEntity.secondParticipantId().map(playerId::equals).orElse(false);

        return ownerIsLocal
                ? new TriadCardItemRenderer.CardPalette(
                        new float[] {0.24F, 0.38F, 0.95F},
                        new float[] {0.08F, 0.16F, 0.62F})
                : new TriadCardItemRenderer.CardPalette(
                        new float[] {0.92F, 0.24F, 0.24F},
                        new float[] {0.56F, 0.10F, 0.10F});
    }
}
