package com.r3944realms.leashedplayer.client.renders.entities;

import com.mojang.blaze3d.vertex.PoseStack;
import com.r3944realms.leashedplayer.content.entities.LittlePlayer;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.model.geom.ModelLayers;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.HumanoidMobRenderer;
import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.item.CrossbowItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.UseAnim;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;

@OnlyIn(Dist.CLIENT)
public class KidPlayerRenderer extends HumanoidMobRenderer<LittlePlayer, PlayerModel<LittlePlayer>>  {


    public static @NotNull KidPlayerRenderer create(@NotNull EntityRendererProvider.Context pContext) {
        if (pContext instanceof PlayerContext pc) {
            return new KidPlayerRenderer(pc);
        }
        return new KidPlayerRenderer(new PlayerContext(pContext, true));
    }

    public static class PlayerContext extends EntityRendererProvider.Context {
        boolean isUseSlimModel;
        public PlayerContext(EntityRendererProvider.Context pContext, boolean pIsSlimModel) {
            super(pContext.getEntityRenderDispatcher(), pContext.getItemRenderer(), pContext.getBlockRenderDispatcher(), pContext.getItemInHandRenderer(), pContext.getResourceManager(), pContext.getModelSet(), pContext.getFont());
            this.isUseSlimModel = pIsSlimModel;
        }

        public boolean isUseSlimModel() {
            return isUseSlimModel;
        }

    }
    public KidPlayerRenderer(PlayerContext pContext) {
        super(pContext, new PlayerModel<>(pContext.bakeLayer(pContext.isUseSlimModel() ? ModelLayers.PLAYER_SLIM : ModelLayers.PLAYER), pContext.isUseSlimModel()), 0.5F);
        this.addLayer(new HumanoidArmorLayer<>(this,
                new HumanoidModel<>(pContext.bakeLayer(ModelLayers.PLAYER_INNER_ARMOR)),
                new HumanoidModel<>(pContext.bakeLayer(ModelLayers.PLAYER_OUTER_ARMOR)),
                pContext.getModelManager()
        ));
    }


    @Override
    public @NotNull ResourceLocation getTextureLocation(@NotNull LittlePlayer pEntity) {
        return pEntity.getSkin().texture();
    }
    public void render(@NotNull LittlePlayer companion, float companionYaw, float pPartialTicks, @NotNull PoseStack pMatrixStack,
                       @NotNull MultiBufferSource pBuffer, int pPackedLight) {
        this.setModelProperties(companion);

        super.render(companion, companionYaw, pPartialTicks, pMatrixStack, pBuffer, pPackedLight);
    }
    private void setModelProperties(LittlePlayer companion) {
        PlayerModel<LittlePlayer> companionModel = this.getModel();

        HumanoidModel.ArmPose humanoidmodel$armpose = getArmPose(companion, InteractionHand.MAIN_HAND);
        HumanoidModel.ArmPose humanoidmodel$armpose1 = getArmPose(companion, InteractionHand.OFF_HAND);

        if (companion.getMainArm() == HumanoidArm.RIGHT) {
            companionModel.rightArmPose = humanoidmodel$armpose;
            companionModel.leftArmPose = humanoidmodel$armpose1;
        } else {
            companionModel.rightArmPose = humanoidmodel$armpose1;
            companionModel.leftArmPose = humanoidmodel$armpose;
        }
    }
    private static HumanoidModel.ArmPose getArmPose(LittlePlayer companion, InteractionHand hand) {
        ItemStack itemstack = companion.getItemInHand(hand);
        if (itemstack.isEmpty()) {
            return HumanoidModel.ArmPose.EMPTY;
        } else {
            if (companion.getUsedItemHand() == hand && companion.getUseItemRemainingTicks() > 0) {
                UseAnim useanim = itemstack.getUseAnimation();

                if (useanim == UseAnim.BOW) {
                    return HumanoidModel.ArmPose.BOW_AND_ARROW;
                }

                if (useanim == UseAnim.CROSSBOW && hand == companion.getUsedItemHand()) {
                    return HumanoidModel.ArmPose.CROSSBOW_CHARGE;
                }
            } else if (!companion.swinging && itemstack.is(Items.CROSSBOW) && CrossbowItem.isCharged(itemstack)) {
                return HumanoidModel.ArmPose.CROSSBOW_HOLD;
            }

            return HumanoidModel.ArmPose.ITEM;
        }
    }
    protected void scale(@NotNull LittlePlayer player, PoseStack pPoseStack, float pPartialTickTime) {
        float f = 0.9375F;
        pPoseStack.scale(f, f, f);
    }

}
