package com.r3944realms.leashedplayer;

import com.r3944realms.leashedplayer.client.renderer.LeashRendererUtil;
import com.r3944realms.leashedplayer.client.renderer.PlayerLeashState;
import com.r3944realms.leashedplayer.client.renderer.entities.ChestItemLayerRenderer;
import com.r3944realms.leashedplayer.client.renderer.entities.LeashRopeArrowRenderer;
import com.r3944realms.leashedplayer.client.renderer.entities.SpectralLeashRopeArrowRenderer;
import com.r3944realms.leashedplayer.client.renderer.item.ConditionalRangeItemModel;
import com.r3944realms.leashedplayer.client.renderer.item.properties.conditional.ChargeExtend;
import com.r3944realms.leashedplayer.content.ModKeyMapping;
import com.r3944realms.leashedplayer.content.entities.ModEntityRegister;
import com.r3944realms.leashedplayer.modInterface.IPlayerRenderStateExtension;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
import com.r3944realms.leashedplayer.network.server.Code;
import com.r3944realms.leashedplayer.network.server.DecreaseLeashRopeLength;
import com.r3944realms.leashedplayer.network.server.IncreaseLeashRopeLength;
import com.r3944realms.leashedplayer.utils.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
import net.minecraft.client.resources.PlayerSkin;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.HitResult;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.*;
import net.neoforged.neoforge.network.PacketDistributor;

import java.util.List;


public class ClientEventHandler {
    @EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.GAME, modid = LeashedPlayer.MOD_ID)
    public static class Game {
        @SubscribeEvent
        public static void onPlayerRendererEventPre(RenderPlayerEvent.Post event) {
            PlayerRenderState renderState = event.getRenderState();
            PlayerLeashState playerLeashState = ((IPlayerRenderStateExtension) renderState).getPlayerLeashState();
            if(playerLeashState != null) {
                if (playerLeashState.vanilaLeashState != null)
                    LeashRendererUtil.renderLeash(event.getPoseStack(), event.getMultiBufferSource(), playerLeashState.vanilaLeashState);
                else
                    LeashRendererUtil.renderLeash(event.getPoseStack(), event.getMultiBufferSource(), renderState);
            }
        }
        @SubscribeEvent
        public static void onKetBoardInput(InputEvent.Key event) {
            Minecraft minecraft = Minecraft.getInstance();
            LocalPlayer player = minecraft.player;
            assert player != null;
            if (ModKeyMapping.KEY_ADD_LEASH_LENGTH.isDown()) {
                PlayerLeashable playerLeashable = (PlayerLeashable) player;
                if (playerLeashable.getLeashData() == null) {
                    assert minecraft.level != null;
                    List<HitResult> refLookAtEntityHitResult = Util.getRefLookAtEntityHitResult(player, minecraft.level, 32, entity -> entity instanceof LivingEntity);
                    Entity theNearestEntityFromHitResultList = Util.getTheNearestEntityFromHitResultList(player, refLookAtEntityHitResult);
                    if(theNearestEntityFromHitResultList != null) {
                        if (theNearestEntityFromHitResultList instanceof Player refPlayer) {
                            PacketDistributor.sendToServer(new IncreaseLeashRopeLength(Code.OTHER_ST, refPlayer.getStringUUID()));
                        }
                    }
                }
                if (playerLeashable.getLeashData() != null) {
                    PacketDistributor.sendToServer(new IncreaseLeashRopeLength(Code.SELF, player.getStringUUID()));
                }
            }
            if (ModKeyMapping.KEY_SUB_LEASH_LENGTH.isDown()) {
                PlayerLeashable playerLeashable = (PlayerLeashable) player;
                if (playerLeashable.getLeashData() == null) {
                    assert minecraft.level != null;
                    List<HitResult> refLookAtEntityHitResult = Util.getRefLookAtEntityHitResult(player, minecraft.level, 32, entity -> entity instanceof LivingEntity);
                    Entity theNearestEntityFromHitResultList = Util.getTheNearestEntityFromHitResultList(player, refLookAtEntityHitResult);
                    if(theNearestEntityFromHitResultList != null) {
                        if (theNearestEntityFromHitResultList instanceof Player refPlayer) {
                            PacketDistributor.sendToServer(new DecreaseLeashRopeLength(Code.OTHER_ST, refPlayer.getStringUUID()));
                        }
                    }
                }
                if (playerLeashable.getLeashData() != null) {
                    PacketDistributor.sendToServer(new DecreaseLeashRopeLength(Code.SELF, player.getStringUUID()));
                }
            }
        }
    }

    @EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD, modid = LeashedPlayer.MOD_ID)
    public static class Mod {
        @SubscribeEvent
        public static void onRegisterItemModels(RegisterItemModelsEvent event) {
            event.register(ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "conditional_range"), ConditionalRangeItemModel.Unbaked.MAP_CODEC);
        }
        @SubscribeEvent
        public static void registrySelectItemModelProperty(RegisterSelectItemModelPropertyEvent event) {
            event.register(ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "charge_extend_type"), ChargeExtend.TYPE);
        }
        @SubscribeEvent
        public static void registerKeyMapping(RegisterKeyMappingsEvent event) {
            event.register(ModKeyMapping.KEY_ADD_LEASH_LENGTH);
            event.register(ModKeyMapping.KEY_SUB_LEASH_LENGTH);
        }
        @SubscribeEvent
        public static void onAddLayers (EntityRenderersEvent.AddLayers event){
            PlayerRenderer renderer = event.getSkin(PlayerSkin.Model.WIDE);
            if (renderer instanceof PlayerRenderer playerRenderer) {
                playerRenderer.addLayer(new ChestItemLayerRenderer<>(playerRenderer, event.getContext().getEntityRenderDispatcher().getItemInHandRenderer()));
            }
            PlayerRenderer slimRenderer = event.getSkin(PlayerSkin.Model.SLIM);
            if (slimRenderer instanceof PlayerRenderer slimPlayerRenderer) {
                slimPlayerRenderer.addLayer(new ChestItemLayerRenderer<>(slimPlayerRenderer, event.getContext().getEntityRenderDispatcher().getItemInHandRenderer()));
            }
        }
        @SubscribeEvent
        public static void RegisterRenderer(EntityRenderersEvent.RegisterRenderers event) {
            event.registerEntityRenderer(ModEntityRegister.LEASH_ROPE_ARROW.get(), LeashRopeArrowRenderer::new);
            event.registerEntityRenderer(ModEntityRegister.SPECTRAL_LEASH_ROPE_ARROW.get(), SpectralLeashRopeArrowRenderer::new);
        }
    }


}
