package dev.crucifixbeta.api.events.eventbus;

import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.function.Consumer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;

@Environment(EnvType.CLIENT)
public class LambdaListener implements IListener {
   private static Method privateLookupInMethod;
   private final Class<?> target;
   private final boolean isStatic;
   private final int priority;
   private Consumer<Object> executor;

   public LambdaListener(LambdaListener.Factory factory, Class<?> klass, Object object, Method method) {
      this.target = method.getParameters()[0].getType();
      this.isStatic = Modifier.isStatic(method.getModifiers());
      this.priority = method.getAnnotation(EventListener.class).priority();

      try {
         String var5 = method.getName();
         Lookup var6 = factory.create(privateLookupInMethod, klass);
         MethodType var7 = MethodType.methodType(void.class, method.getParameters()[0].getType());
         MethodHandle var8;
         MethodType var9;
         if (this.isStatic) {
            var8 = var6.findStatic(klass, var5, var7);
            var9 = MethodType.methodType(Consumer.class);
         } else {
            var8 = var6.findVirtual(klass, var5, var7);
            var9 = MethodType.methodType(Consumer.class, klass);
         }

         MethodHandle var10 = LambdaMetafactory.metafactory(
               var6, "accept", var9, MethodType.methodType(void.class, Object.class), var8, var7
            )
            .getTarget();
         this.executor = (Consumer<Object>)(this.isStatic ? (Object)var10.invoke() : (Object)var10.invoke((Object)object));
      } catch (Throwable var11) {
         var11.printStackTrace();
      }
   }

   @Override
   public void call(Object event) {
      this.executor.accept(event);
   }

   @Override
   public Class<?> getTarget() {
      return this.target;
   }

   @Override
   public int getPriority() {
      return this.priority;
   }

   @Override
   public boolean isStatic() {
      return this.isStatic;
   }

   static {

      try {
         privateLookupInMethod = MethodHandles.class.getDeclaredMethod("privateLookupIn", Class.class, Lookup.class);
      } catch (NoSuchMethodException var8) {
         var8.printStackTrace();
      }
   }
@Environment(EnvType.CLIENT)
   public interface Factory {
      Lookup create(Method method, Class<?> class_) throws InvocationTargetException, IllegalAccessException;
   }
}
