package dev.crucifixbeta.core.impl;

import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.utils.Wrapper;
import dev.crucifixbeta.api.utils.world.BlockUtil;
import dev.crucifixbeta.mod.modules.impl.combat.Breaker;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;

@Environment(EnvType.CLIENT)
public class HoleManager implements Wrapper {
   public boolean isHole(BlockPos pos) {
      return this.isHole(pos, true, false, false);
   }

   public boolean isHole(BlockPos pos, boolean canStand, boolean checkTrap, boolean anyBlock) {
      int var5 = 0;

      for (Direction var9 : Direction.values()) {
         if (var9 != Direction.UP && var9 != Direction.DOWN && (anyBlock && !mc.world.isAir(pos.offset(var9)) || CrucifixBeta.HOLE.isHard(pos.offset(var9)))) {
            var5++;
         }
      }

      return (
            !checkTrap
               || mc.world.isAir(pos)
                  && mc.world.isAir(pos.up())
                  && mc.world.isAir(pos.up(1))
                  && mc.world.isAir(pos.up(2))
                  && (mc.player.getBlockY() - 1 <= pos.getY() || mc.world.isAir(pos.up(3)))
                  && (mc.player.getBlockY() - 2 <= pos.getY() || mc.world.isAir(pos.up(4)))
         )
         && var5 > 3
         && (!canStand || BlockUtil.canCollide(new Box(pos.add(0, -1, 0))));
   }

   public BlockPos getHole(float range, boolean doubleHole, boolean any, boolean up) {
      BlockPos var5 = null;
      double var6 = (double)(range + 1.0F);

      for (BlockPos var9 : BlockUtil.getSphere(range, mc.player.getPos())) {
         if ((var9.getX() == mc.player.getBlockX() && var9.getZ() == mc.player.getBlockZ() || up || !((double)(var9.getY() + 1) > mc.player.getY()))
            && (CrucifixBeta.HOLE.isHole(var9, true, true, any) || doubleHole && this.isDoubleHole(var9))
            && var9.getY() - mc.player.getBlockY() <= 1) {
            double var10 = (double)MathHelper.sqrt(
               (float)mc.player.squaredDistanceTo((double)var9.getX() + 0.5, (double)var9.getY() + 0.5, (double)var9.getZ() + 0.5)
            );
            if (var5 == null || var10 < var6) {
               var5 = var9;
               var6 = var10;
            }
         }
      }

      return var5;
   }

   public boolean isDoubleHole(BlockPos pos) {
      Direction var2 = this.is3Block(pos);
      return var2 != null ? this.is3Block(pos.offset(var2)) != null : false;
   }

   public Direction is3Block(BlockPos pos) {
      if (!this.isHard(pos.down())) {
         return null;
      } else if (mc.world.isAir(pos) && mc.world.isAir(pos.up()) && mc.world.isAir(pos.up(2))) {
         int var2 = 0;
         Direction var3 = null;

         for (Direction var7 : Direction.values()) {
            if (var7 != Direction.UP && var7 != Direction.DOWN) {
               if (this.isHard(pos.offset(var7))) {
                  var2++;
               } else {
                  int var8 = 0;

                  for (Direction var12 : Direction.values()) {
                     if (var12 != Direction.DOWN && var12 != var7.getOpposite() && this.isHard(pos.offset(var7).offset(var12))) {
                        var8++;
                     }
                  }

                  if (var8 == 4) {
                     var2++;
                  } else {
                     var3 = var7;
                  }
               }
            }
         }

         return var2 == 3 ? var3 : null;
      } else {
         return null;
      }
   }

   public boolean isHard(BlockPos pos) {
      Block var2 = mc.world.getBlockState(pos).getBlock();
      return this.isHard(var2);
   }

   public boolean isHard(Block block) {
      return block == Blocks.BEDROCK || Breaker.hard.contains(block);
   }
}
