/*
 * Decompiled with CFR 0.152.
 * 
 * Could not load the following classes:
 *  meteordevelopment.orbit.EventHandler
 *  net.minecraft.class_1802
 *  net.minecraft.class_1923
 *  net.minecraft.class_2246
 *  net.minecraft.class_2248
 *  net.minecraft.class_2338
 *  net.minecraft.class_2338$class_2339
 *  net.minecraft.class_2680
 *  net.minecraft.class_2791
 *  net.minecraft.class_2818
 *  net.minecraft.class_2902$class_2903
 *  net.minecraft.class_368
 */
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 meteordevelopment.meteorclient.events.render.Render3DEvent;
import meteordevelopment.meteorclient.events.world.BlockUpdateEvent;
import meteordevelopment.meteorclient.events.world.ChunkDataEvent;
import meteordevelopment.meteorclient.renderer.ShapeMode;
import meteordevelopment.meteorclient.settings.ColorSetting;
import meteordevelopment.meteorclient.settings.EnumSetting;
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.Utils;
import meteordevelopment.meteorclient.utils.render.MeteorToast;
import meteordevelopment.meteorclient.utils.render.color.Color;
import meteordevelopment.meteorclient.utils.render.color.SettingColor;
import meteordevelopment.orbit.EventHandler;
import net.minecraft.class_1802;
import net.minecraft.class_1923;
import net.minecraft.class_2246;
import net.minecraft.class_2248;
import net.minecraft.class_2338;
import net.minecraft.class_2680;
import net.minecraft.class_2791;
import net.minecraft.class_2818;
import net.minecraft.class_2902;
import net.minecraft.class_368;

public class KelpEsp
extends Module {
    private final SettingGroup sgGeneral;
    private final Setting<SettingColor> kelpColor;
    private final Setting<ShapeMode> kelpShapeMode;
    private final Setting<Integer> minKelpColumns;
    private final Setting<Integer> minTopsAt62;
    private final Set<class_1923> flaggedKelpChunks;
    private final Set<class_1923> notifiedChunks;
    private final Set<class_1923> scannedChunks;
    private ExecutorService threadPool;

    public KelpEsp() {
        super(Categories.Donut, "Kelp esp", "Highlights near-perfect kelp farm chunks using threaded scanning.");
        this.sgGeneral = this.settings.getDefaultGroup();
        this.kelpColor = this.sgGeneral.add(((ColorSetting.Builder)new ColorSetting.Builder().name("esp-color")).defaultValue(new SettingColor(0, 255, 0, 100)).build());
        this.kelpShapeMode = this.sgGeneral.add(((EnumSetting.Builder)((EnumSetting.Builder)new EnumSetting.Builder().name("shape-mode")).defaultValue(ShapeMode.Both)).build());
        this.minKelpColumns = this.sgGeneral.add(((IntSetting.Builder)((IntSetting.Builder)new IntSetting.Builder().name("min-kelp-columns")).defaultValue(20)).min(1).build());
        this.minTopsAt62 = this.sgGeneral.add(((IntSetting.Builder)((IntSetting.Builder)new IntSetting.Builder().name("min-tops-at-y62")).defaultValue(18)).min(1).build());
        this.flaggedKelpChunks = ConcurrentHashMap.newKeySet();
        this.notifiedChunks = ConcurrentHashMap.newKeySet();
        this.scannedChunks = ConcurrentHashMap.newKeySet();
    }

    @Override
    public void onActivate() {
        this.clearData();
        this.threadPool = Executors.newFixedThreadPool(2);
        if (this.mc.field_1687 == null) {
            return;
        }
        for (class_2791 chunk : Utils.chunks()) {
            if (!(chunk instanceof class_2818)) continue;
            class_2818 worldChunk = (class_2818)chunk;
            this.threadPool.submit(() -> this.scanChunk(worldChunk));
        }
    }

    @Override
    public void onDeactivate() {
        if (this.threadPool != null) {
            this.threadPool.shutdownNow();
        }
        this.clearData();
    }

    private void clearData() {
        this.flaggedKelpChunks.clear();
        this.notifiedChunks.clear();
        this.scannedChunks.clear();
    }

    @EventHandler
    private void onChunkLoad(ChunkDataEvent event) {
        if (this.threadPool != null && !this.threadPool.isShutdown()) {
            this.threadPool.submit(() -> this.scanChunk(event.chunk()));
        }
    }

    @EventHandler
    private void onBlockUpdate(BlockUpdateEvent event) {
        class_2248 newBlock = event.newState.method_26204();
        class_2248 oldBlock = event.oldState.method_26204();
        if (this.isKelp(newBlock) || this.isKelp(oldBlock)) {
            class_2791 chunk;
            class_1923 cp = new class_1923(event.pos);
            this.scannedChunks.remove(cp);
            if (this.threadPool != null && !this.threadPool.isShutdown() && this.mc.field_1687 != null && (chunk = this.mc.field_1687.method_22350(event.pos)) instanceof class_2818) {
                class_2818 worldChunk = (class_2818)chunk;
                this.threadPool.submit(() -> this.scanChunk(worldChunk));
            }
        }
    }

    @EventHandler
    private void onRender(Render3DEvent event) {
        if (this.mc.field_1687 == null) {
            return;
        }
        Color side = new Color(this.kelpColor.get());
        Color line = new Color(side);
        line.a = 255;
        for (class_1923 pos : this.flaggedKelpChunks) {
            double x1 = pos.method_8326();
            double z1 = pos.method_8328();
            event.renderer.box(x1, 62.9, z1, x1 + 16.0, 63.1, z1 + 16.0, side, line, this.kelpShapeMode.get(), 0);
        }
    }

    private void scanChunk(class_2818 chunk) {
        class_1923 cpos = chunk.method_12004();
        if (!this.scannedChunks.add(cpos)) {
            return;
        }
        int kelpColumns = 0;
        int kelpTopsAt62 = 0;
        class_2338.class_2339 mutable = new class_2338.class_2339();
        for (int x = 0; x < 16; ++x) {
            for (int z = 0; z < 16; ++z) {
                int surfaceY = chunk.method_12032(class_2902.class_2903.field_13202).method_12603(x, z);
                if (surfaceY < 30 || surfaceY > 62) continue;
                mutable.method_10103(cpos.method_8326() + x, surfaceY, cpos.method_8328() + z);
                class_2680 state = chunk.method_8320((class_2338)mutable);
                if (!this.isKelp(state.method_26204())) continue;
                ++kelpColumns;
                if (surfaceY != 62) continue;
                ++kelpTopsAt62;
            }
        }
        if (kelpColumns >= this.minKelpColumns.get() && kelpTopsAt62 >= this.minTopsAt62.get()) {
            this.flaggedKelpChunks.add(cpos);
            if (this.notifiedChunks.add(cpos)) {
                this.sendFeedback(cpos, kelpTopsAt62, kelpColumns);
            }
        } else {
            this.flaggedKelpChunks.remove(cpos);
        }
    }

    private boolean isKelp(class_2248 block) {
        return block == class_2246.field_9993 || block == class_2246.field_10463;
    }

    private void sendFeedback(class_1923 cpos, int tops, int total) {
        this.mc.execute(() -> {
            if (this.mc.field_1724 == null) {
                return;
            }
            this.info("Perfect kelp chunk at [%d, %d] (%d/%d tops)", cpos.field_9181, cpos.field_9180, tops, total);
            this.mc.method_1566().method_1999((class_368)new MeteorToast.Builder("KelpESP").icon(class_1802.field_17532).text("X: " + cpos.field_9181 + " Z: " + cpos.field_9180).build());
        });
    }
}

