/*
 * Decompiled with CFR 0.152.
 * 
 * Could not load the following classes:
 *  meteordevelopment.orbit.EventHandler
 *  net.minecraft.class_1923
 *  net.minecraft.class_1944
 *  net.minecraft.class_2246
 *  net.minecraft.class_2338
 *  net.minecraft.class_2350
 *  net.minecraft.class_2586
 *  net.minecraft.class_2596
 *  net.minecraft.class_2626
 *  net.minecraft.class_2636
 *  net.minecraft.class_2818
 */
package meteordevelopment.meteorclient.systems.modules.donut;

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import meteordevelopment.meteorclient.events.packets.PacketEvent;
import meteordevelopment.meteorclient.events.render.Render3DEvent;
import meteordevelopment.meteorclient.events.world.TickEvent;
import meteordevelopment.meteorclient.renderer.ShapeMode;
import meteordevelopment.meteorclient.settings.BoolSetting;
import meteordevelopment.meteorclient.settings.ColorSetting;
import meteordevelopment.meteorclient.settings.IntSetting;
import meteordevelopment.meteorclient.settings.Setting;
import meteordevelopment.meteorclient.settings.SettingGroup;
import meteordevelopment.meteorclient.systems.modules.Categories;
import meteordevelopment.meteorclient.systems.modules.Module;
import meteordevelopment.meteorclient.utils.render.color.SettingColor;
import meteordevelopment.orbit.EventHandler;
import net.minecraft.class_1923;
import net.minecraft.class_1944;
import net.minecraft.class_2246;
import net.minecraft.class_2338;
import net.minecraft.class_2350;
import net.minecraft.class_2586;
import net.minecraft.class_2596;
import net.minecraft.class_2626;
import net.minecraft.class_2636;
import net.minecraft.class_2818;

public class SpawnerDetect
extends Module {
    private final SettingGroup sgDetection;
    private final SettingGroup sgRender;
    private final Setting<Boolean> strictBlockEntity;
    private final Setting<Boolean> detectLightAnomalies;
    private final Setting<Integer> scanRadius;
    private final Setting<SettingColor> sideColor;
    private final Setting<SettingColor> lineColor;
    private final Set<class_1923> spawnerChunks;
    private final Set<class_1923> notified;
    private final ExecutorService executor;
    private final AtomicBoolean isScanning;
    private int scanTicks;

    public SpawnerDetect() {
        super(Categories.Donut, "spawner-detect", "Strict spawner detection. Only flags high-confidence signals under deepslate.");
        this.sgDetection = this.settings.createGroup("Detection");
        this.sgRender = this.settings.createGroup("Render");
        this.strictBlockEntity = this.sgDetection.add(((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("strict-spawner-scan")).description("Strictly search for spawner block entities.")).defaultValue(true)).build());
        this.detectLightAnomalies = this.sgDetection.add(((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("light-anomalies")).description("Detect spawners in lit rooms under deepslate.")).defaultValue(true)).build());
        this.scanRadius = this.sgDetection.add(((IntSetting.Builder)((IntSetting.Builder)new IntSetting.Builder().name("scan-radius")).defaultValue(12)).range(1, 32).build());
        this.sideColor = this.sgRender.add(((ColorSetting.Builder)new ColorSetting.Builder().name("side-color")).defaultValue(new SettingColor(255, 255, 255, 45)).build());
        this.lineColor = this.sgRender.add(((ColorSetting.Builder)new ColorSetting.Builder().name("line-color")).defaultValue(new SettingColor(255, 255, 255, 200)).build());
        this.spawnerChunks = ConcurrentHashMap.newKeySet();
        this.notified = ConcurrentHashMap.newKeySet();
        this.executor = Executors.newSingleThreadExecutor();
        this.isScanning = new AtomicBoolean(false);
        this.scanTicks = 0;
    }

    @Override
    public void onActivate() {
        this.spawnerChunks.clear();
        this.notified.clear();
    }

    @EventHandler
    private void onTick(TickEvent.Post event) {
        if (this.mc.field_1687 == null || this.mc.field_1724 == null) {
            return;
        }
        ++this.scanTicks;
        if (this.scanTicks >= 100) {
            this.scanTicks = 0;
            if (this.isScanning.compareAndSet(false, true)) {
                this.executor.execute(this::scan);
            }
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private void scan() {
        try {
            if (this.mc.field_1687 == null || this.mc.field_1724 == null) {
                return;
            }
            class_1923 center = this.mc.field_1724.method_31476();
            int radius = this.scanRadius.get();
            for (int x = -radius; x <= radius; ++x) {
                for (int z = -radius; z <= radius; ++z) {
                    class_2818 chunk = this.mc.field_1687.method_2935().method_21730(center.field_9181 + x, center.field_9180 + z);
                    if (chunk == null) continue;
                    this.processChunk(chunk);
                }
            }
        }
        finally {
            this.isScanning.set(false);
        }
    }

    private void processChunk(class_2818 chunk) {
        class_1923 cp = chunk.method_12004();
        if (this.strictBlockEntity.get().booleanValue()) {
            for (class_2586 be : chunk.method_12214().values()) {
                if (!(be instanceof class_2636)) continue;
                this.addSpawner(be.method_11016(), "spawner entity");
                return;
            }
        }
        if (this.detectLightAnomalies.get().booleanValue()) {
            int anomalies = 0;
            for (int y = chunk.method_31607(); y < 0; y += 4) {
                for (int x = 0; x < 16; x += 4) {
                    for (int z = 0; z < 16; z += 4) {
                        class_2338 pos = new class_2338(cp.method_8326() + x, y, cp.method_8328() + z);
                        if (this.mc.field_1687.method_8314(class_1944.field_9282, pos) <= 11 || chunk.method_8320(pos).method_26213() != 0 || !this.isAnomalousArea(chunk, pos)) continue;
                        ++anomalies;
                    }
                }
            }
            if (anomalies > 8) {
                this.addSpawner(new class_2338(cp.method_8326() + 8, -32, cp.method_8328() + 8), "lit spawner room");
            }
        }
    }

    private boolean isAnomalousArea(class_2818 chunk, class_2338 pos) {
        int neighborsWithLight = 0;
        for (class_2350 dir : class_2350.values()) {
            class_2338 nPos = pos.method_10093(dir);
            if (this.mc.field_1687.method_8314(class_1944.field_9282, nPos) <= 8) continue;
            ++neighborsWithLight;
        }
        return neighborsWithLight >= 2;
    }

    @EventHandler
    private void onPacket(PacketEvent.Receive event) {
        class_2626 p;
        if (this.mc.field_1687 == null) {
            return;
        }
        class_2596<?> class_25962 = event.packet;
        if (class_25962 instanceof class_2626 && (p = (class_2626)class_25962).method_11308().method_27852(class_2246.field_10260)) {
            this.addSpawner(p.method_11309(), "placed spawner");
        }
    }

    private void addSpawner(class_2338 pos, String reason) {
        class_1923 cp = new class_1923(pos);
        if (this.spawnerChunks.add(cp) && this.notified.add(cp)) {
            this.info("(highlight)Spawner detected(default) at %d, %d via %s!", pos.method_10263(), pos.method_10260(), reason);
        }
    }

    @EventHandler
    private void onRender3D(Render3DEvent event) {
        for (class_1923 pos : this.spawnerChunks) {
            double x1 = pos.method_8326();
            double z1 = pos.method_8328();
            double x2 = x1 + 16.0;
            double z2 = z1 + 16.0;
            event.renderer.box(x1, this.mc.field_1687.method_31607(), z1, x2, this.mc.field_1687.method_31600(), z2, this.sideColor.get(), this.lineColor.get(), ShapeMode.Both, 0);
        }
    }
}

