package dev.crucifixbeta.core.impl;

import com.google.common.collect.Lists;
import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.events.eventbus.EventListener;
import dev.crucifixbeta.api.events.impl.ClientTickEvent;
import dev.crucifixbeta.api.events.impl.UpdateEvent;
import dev.crucifixbeta.api.utils.Wrapper;
import dev.crucifixbeta.api.utils.render.JelloUtil;
import dev.crucifixbeta.api.utils.world.BlockUtil;
import dev.crucifixbeta.mod.modules.Module;
import dev.crucifixbeta.mod.modules.impl.client.ClientSetting;
import dev.crucifixbeta.mod.modules.impl.combat.AutoAnchor;
import dev.crucifixbeta.mod.modules.impl.combat.AutoCrystal;
import dev.crucifixbeta.mod.modules.impl.render.HoleESP;
import dev.crucifixbeta.mod.modules.impl.render.PlaceRender;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.entity.Entity;

@Environment(EnvType.CLIENT)
public class ThreadManager implements Wrapper {
   public static final ExecutorService EXECUTOR;
   public static ThreadManager.ClientService clientService;
   public volatile Iterable<Entity> threadSafeEntityList = Collections.emptyList();
   public volatile List<AbstractClientPlayerEntity> threadSafePlayersList = Collections.emptyList();
   public volatile boolean tickRunning = false;

   public ThreadManager() {
      this.init();
   }

   public void init() {
      CrucifixBeta.EVENT_BUS.subscribe(this);
      clientService = new ThreadManager.ClientService();
      clientService.setName("FrogClientService");
      clientService.setDaemon(true);
      clientService.start();
   }

   public Iterable<Entity> getEntities() {
      return this.threadSafeEntityList;
   }

   public List<AbstractClientPlayerEntity> getPlayers() {
      return this.threadSafePlayersList;
   }

   public void execute(Runnable runnable) {
      EXECUTOR.execute(runnable);
   }

   @EventListener(
      priority = 200
   )
   public void onEvent(ClientTickEvent event) {
      CrucifixBeta.POP.onUpdate();
      CrucifixBeta.SERVER.onUpdate();
      if (event.isPre()) {
         JelloUtil.updateJello();
         this.tickRunning = true;
         BlockUtil.placedPos.forEach(pos -> PlaceRender.INSTANCE.create(pos));
         BlockUtil.placedPos.clear();
         CrucifixBeta.PLAYER.onUpdate();
         if (!Module.nullCheck()) {
            CrucifixBeta.EVENT_BUS.post(UpdateEvent.INSTANCE);
         }
      } else {
         this.tickRunning = false;
         if (mc.world == null || mc.player == null) {
            return;
         }

         this.threadSafeEntityList = Lists.newArrayList(mc.world.getEntities());
         this.threadSafePlayersList = Lists.newArrayList(mc.world.getPlayers());
      }

      if (!clientService.isAlive() || clientService.isInterrupted()) {
         clientService = new ThreadManager.ClientService();
         clientService.setName("FrogService");
         clientService.setDaemon(true);
         clientService.start();
      }
   }

   static {

      EXECUTOR = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
   }
@Environment(EnvType.CLIENT)
   public class ClientService extends Thread {
      @Override
      public void run() {
         long var1 = 0L;

         while (true) {
            try {
               if (ThreadManager.this.tickRunning) {
                  Thread.sleep(5L);
               } else {
                  AutoCrystal.INSTANCE.onThread();
                  AutoAnchor.INSTANCE.onThread();
                  HoleESP.INSTANCE.onThread();
                  Thread.sleep(10L);
               }
            } catch (InterruptedException var8) {
               Thread.currentThread().interrupt();
               return;
            } catch (Exception var9) {
               var9.printStackTrace();
               if (ClientSetting.INSTANCE.debug.getValue()) {
                  CommandManager.sendMessage("§4An error has occurred [Thread] Message: [" + var9.getMessage() + "]");
               }

               try {
                  long var4 = System.currentTimeMillis();
                  if (var4 - var1 < 50L) {
                     Thread.sleep(50L - (var4 - var1));
                  } else {
                     Thread.sleep(50L);
                  }

                  var1 = System.currentTimeMillis();
               } catch (InterruptedException var7) {
                  Thread.currentThread().interrupt();
                  return;
               }
            }
         }
      }
   }
}
