package net.fabricmc.fabric.mixin.client.rendering;

import com.google.common.collect.ImmutableMap;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import java.util.Map;
import java.util.Objects;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.rendering.v1.LivingEntityFeatureRendererRegistrationCallback;
import net.fabricmc.fabric.impl.client.rendering.EntityRendererRegistryImpl;
import net.fabricmc.fabric.impl.client.rendering.RegistrationHelperImpl;
import net.minecraft.class_1007;
import net.minecraft.class_1299;
import net.minecraft.class_5617;
import net.minecraft.class_5619;
import net.minecraft.class_897;
import net.minecraft.class_922;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Environment(EnvType.CLIENT)
@Mixin({class_5619.class})
public abstract class EntityRendererFactoriesMixin {
   @Shadow
   @Final
   private static Map<class_1299<?>, class_5617<?>> field_27768;

   @Inject(
      method = {"<clinit>*"},
      at = {@At("RETURN")}
   )
   private static void onRegisterRenderers(CallbackInfo info) {
      EntityRendererRegistryImpl.setup((t, factory) -> field_27768.put(t, factory));
   }

   @Redirect(
      method = {"method_32174(Lcom/google/common/collect/ImmutableMap$Builder;Lnet/minecraft/class_5617$class_5618;Lnet/minecraft/class_1299;Lnet/minecraft/class_5617;)V"},
      at = @At(
   value = "INVOKE",
   target = "Lnet/minecraft/class_5617;create(Lnet/minecraft/class_5617$class_5618;)Lnet/minecraft/class_897;"
)
   )
   private static class_897<?, ?> createEntityRenderer(class_5617<?> entityRendererFactory, class_5617.class_5618 context, ImmutableMap.Builder builder, class_5617.class_5618 context2, class_1299<?> entityType) {
      class_897<?, ?> entityRenderer = entityRendererFactory.create(context);
      if (entityRenderer instanceof class_922) {
         LivingEntityRendererAccessor accessor = (LivingEntityRendererAccessor)entityRenderer;
         LivingEntityFeatureRendererRegistrationCallback var10000 = (LivingEntityFeatureRendererRegistrationCallback)LivingEntityFeatureRendererRegistrationCallback.EVENT.invoker();
         class_922 var10002 = (class_922)entityRenderer;
         Objects.requireNonNull(accessor);
         var10000.registerRenderers(entityType, var10002, new RegistrationHelperImpl(accessor::callAddFeature), context);
      }

      return entityRenderer;
   }

   @WrapOperation(
      method = {"method_32177(Lnet/minecraft/class_5617$class_5618;)Ljava/util/Map;"},
      at = {@At(
   value = "NEW",
   target = "(Lnet/minecraft/class_5617$class_5618;Z)Lnet/minecraft/class_1007;"
)}
   )
   private static class_1007 createPlayerEntityRenderer(class_5617.class_5618 context, boolean slim, Operation<class_1007> original) {
      class_1007 entityRenderer = (class_1007)original.call(new Object[]{context, slim});
      LivingEntityRendererAccessor accessor = (LivingEntityRendererAccessor)entityRenderer;
      LivingEntityFeatureRendererRegistrationCallback var10000 = (LivingEntityFeatureRendererRegistrationCallback)LivingEntityFeatureRendererRegistrationCallback.EVENT.invoker();
      class_1299 var10001 = class_1299.field_6097;
      Objects.requireNonNull(accessor);
      var10000.registerRenderers(var10001, entityRenderer, new RegistrationHelperImpl(accessor::callAddFeature), context);
      return entityRenderer;
   }
}
