/*
 * 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_2248
 *  net.minecraft.class_2338
 *  net.minecraft.class_2350
 *  net.minecraft.class_2586
 *  net.minecraft.class_2818
 */
package meteordevelopment.meteorclient.systems.modules.donut;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
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.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_2248;
import net.minecraft.class_2338;
import net.minecraft.class_2350;
import net.minecraft.class_2586;
import net.minecraft.class_2818;

public class SignalScanner
extends Module {
    private final SettingGroup sgGeneral;
    private final SettingGroup sgRender;
    private final Setting<Integer> scanRadius;
    private final Setting<Integer> scanInterval;
    private final Setting<Boolean> detectBlockEntities;
    private final Setting<Boolean> detectLightAnomalies;
    private final Setting<Boolean> chatNotify;
    private final Setting<SettingColor> sideColor;
    private final Setting<SettingColor> lineColor;
    private final Map<class_1923, Signal> signals;
    private final Set<class_1923> announced;
    private final ExecutorService executor;
    private final AtomicBoolean isScanning;
    private int ticks;

    public SignalScanner() {
        super(Categories.Donut, "signal-scanner", "Detects anomalous signals (light, block entities) in remote chunks to find bases.");
        this.sgGeneral = this.settings.getDefaultGroup();
        this.sgRender = this.settings.createGroup("Render");
        this.scanRadius = this.sgGeneral.add(((IntSetting.Builder)((IntSetting.Builder)((IntSetting.Builder)new IntSetting.Builder().name("scan-radius")).description("How far out (chunks) to look for signals.")).defaultValue(12)).range(1, 32).sliderRange(5, 20).build());
        this.scanInterval = this.sgGeneral.add(((IntSetting.Builder)((IntSetting.Builder)((IntSetting.Builder)new IntSetting.Builder().name("scan-interval")).description("Ticks between scans.")).defaultValue(20)).range(1, 100).sliderRange(5, 60).build());
        this.detectBlockEntities = this.sgGeneral.add(((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("detect-block-entities")).description("Scan for hidden chests, spawners, and other block entities.")).defaultValue(true)).build());
        this.detectLightAnomalies = this.sgGeneral.add(((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("light-anomalies")).description("Detect light sources where no light-emitting blocks are visible (bypasses Anti-Xray).")).defaultValue(true)).build());
        this.chatNotify = this.sgGeneral.add(((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("chat-notify")).description("Announce new signal hits in chat.")).defaultValue(true)).build());
        this.sideColor = this.sgRender.add(((ColorSetting.Builder)new ColorSetting.Builder().name("side-color")).defaultValue(new SettingColor(255, 50, 255, 40)).build());
        this.lineColor = this.sgRender.add(((ColorSetting.Builder)new ColorSetting.Builder().name("line-color")).defaultValue(new SettingColor(255, 50, 255, 220)).build());
        this.signals = new ConcurrentHashMap<class_1923, Signal>();
        this.announced = ConcurrentHashMap.newKeySet();
        this.executor = Executors.newSingleThreadExecutor();
        this.isScanning = new AtomicBoolean(false);
        this.ticks = 0;
    }

    @Override
    public void onActivate() {
        this.signals.clear();
        this.announced.clear();
    }

    @EventHandler
    private void onTick(TickEvent.Post event) {
        if (this.mc.field_1687 == null || this.mc.field_1724 == null) {
            return;
        }
        ++this.ticks;
        if (this.ticks >= this.scanInterval.get()) {
            this.ticks = 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) {
                    int cx = center.field_9181 + x;
                    int cz = center.field_9180 + z;
                    class_2818 chunk = this.mc.field_1687.method_2935().method_21730(cx, cz);
                    if (chunk == null) continue;
                    this.processChunk(chunk);
                }
            }
        }
        finally {
            this.isScanning.set(false);
        }
    }

    private void processChunk(class_2818 chunk) {
        Map blockEntities;
        class_1923 cp = chunk.method_12004();
        int score = 0;
        ArrayList<String> reasons = new ArrayList<String>();
        if (this.detectBlockEntities.get().booleanValue() && !(blockEntities = chunk.method_12214()).isEmpty()) {
            int count = 0;
            for (class_2586 be : blockEntities.values()) {
                class_2248 b = be.method_11010().method_26204();
                if (b == class_2246.field_10124) continue;
                ++count;
            }
            if (count > 0) {
                score += count * 5;
                reasons.add(count + " block entities");
            }
        }
        if (this.detectLightAnomalies.get().booleanValue()) {
            int anomalies = 0;
            for (int y = chunk.method_31607(); y < chunk.method_31607() + chunk.method_31605(); y += 8) {
                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);
                        int blockLight = this.mc.field_1687.method_8314(class_1944.field_9282, pos);
                        if (blockLight <= 10 || chunk.method_8320(pos).method_26213() != 0 || !this.isAnomalousArea(chunk, pos)) continue;
                        ++anomalies;
                    }
                }
            }
            if (anomalies > 4) {
                score += anomalies * 10;
                reasons.add("light anomaly cluster (" + anomalies + ")");
            }
        }
        if (score > 0) {
            this.signals.put(cp, new Signal(cp, reasons));
            if (this.chatNotify.get().booleanValue() && this.announced.add(cp)) {
                this.info("(highlight)Signal detected(default) at %d, %d! Reasons: %s", cp.field_9181, cp.field_9180, String.join((CharSequence)", ", reasons));
            }
        }
    }

    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 onRender3D(Render3DEvent event) {
        for (Signal s : this.signals.values()) {
            double x1 = s.pos.method_8326();
            double z1 = s.pos.method_8328();
            double x2 = x1 + 16.0;
            double z2 = z1 + 16.0;
            double y1 = this.mc.field_1687.method_31607();
            double y2 = y1 + (double)this.mc.field_1687.method_31605();
            event.renderer.box(x1, y1, z1, x2, y2, z2, this.sideColor.get(), this.lineColor.get(), ShapeMode.Both, 0);
        }
    }

    private static class Signal {
        final class_1923 pos;
        final List<String> reasons;

        Signal(class_1923 pos, List<String> reasons) {
            this.pos = pos;
            this.reasons = reasons;
        }
    }
}

