/*
 * Decompiled with CFR 0.152.
 * 
 * Could not load the following classes:
 *  meteordevelopment.orbit.EventHandler
 *  net.minecraft.class_1923
 *  net.minecraft.class_1937
 *  net.minecraft.class_2246
 *  net.minecraft.class_2338
 *  net.minecraft.class_2350
 *  net.minecraft.class_2350$class_2351
 *  net.minecraft.class_2680
 *  net.minecraft.class_2741
 *  net.minecraft.class_2769
 *  net.minecraft.class_2791
 *  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 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.BoolSetting;
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.RenderUtils;
import meteordevelopment.meteorclient.utils.render.color.Color;
import meteordevelopment.meteorclient.utils.render.color.SettingColor;
import meteordevelopment.orbit.EventHandler;
import net.minecraft.class_1923;
import net.minecraft.class_1937;
import net.minecraft.class_2246;
import net.minecraft.class_2338;
import net.minecraft.class_2350;
import net.minecraft.class_2680;
import net.minecraft.class_2741;
import net.minecraft.class_2769;
import net.minecraft.class_2791;
import net.minecraft.class_2818;

public class RotatedDeepslate
extends Module {
    private final SettingGroup sgGeneral;
    private final SettingGroup sgFiltering;
    private final SettingGroup sgRange;
    private final Setting<SettingColor> deepslateColor;
    private final Setting<ShapeMode> deepslateShapeMode;
    private final Setting<Boolean> ignoreExposed;
    private final Setting<Boolean> tracers;
    private final Setting<Boolean> includeRegular;
    private final Setting<Boolean> includeBricks;
    private final Setting<Boolean> includeTiles;
    private final Setting<Integer> minY;
    private final Setting<Integer> maxY;
    private final Set<class_2338> rotatedPositions;
    private ExecutorService threadPool;
    private final Color boxColor;
    private final Color lineColor;

    public RotatedDeepslate() {
        super(Categories.Donut, "Rotated Deepslate", "Highlights deepslate blocks that have been rotated by players (axis is not Y).");
        this.sgGeneral = this.settings.createGroup("General");
        this.sgFiltering = this.settings.createGroup("Block Types");
        this.sgRange = this.settings.createGroup("Range");
        this.deepslateColor = this.sgGeneral.add(((ColorSetting.Builder)((ColorSetting.Builder)new ColorSetting.Builder().name("esp-color")).description("The color of the ESP box and tracers.")).defaultValue(new SettingColor(255, 0, 255, 100)).build());
        this.deepslateShapeMode = this.sgGeneral.add(((EnumSetting.Builder)((EnumSetting.Builder)((EnumSetting.Builder)new EnumSetting.Builder().name("shape-mode")).description("How the shapes are rendered.")).defaultValue(ShapeMode.Both)).build());
        this.ignoreExposed = this.sgGeneral.add(((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("ignore-exposed")).description("Only show blocks that are completely buried (not touching air/water).")).defaultValue(true)).build());
        this.tracers = this.sgGeneral.add(((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("tracers")).description("Draw lines from your crosshair to the blocks.")).defaultValue(false)).build());
        this.includeRegular = this.sgFiltering.add(((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("regular-deepslate")).defaultValue(true)).build());
        this.includeBricks = this.sgFiltering.add(((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("deepslate-bricks")).defaultValue(true)).build());
        this.includeTiles = this.sgFiltering.add(((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("deepslate-tiles")).defaultValue(true)).build());
        this.minY = this.sgRange.add(((IntSetting.Builder)((IntSetting.Builder)new IntSetting.Builder().name("min-y")).defaultValue(-64)).sliderRange(-64, 320).build());
        this.maxY = this.sgRange.add(((IntSetting.Builder)((IntSetting.Builder)new IntSetting.Builder().name("max-y")).defaultValue(128)).sliderRange(-64, 320).build());
        this.rotatedPositions = ConcurrentHashMap.newKeySet();
        this.boxColor = new Color();
        this.lineColor = new Color();
    }

    @Override
    public void onActivate() {
        this.rotatedPositions.clear();
        this.threadPool = Executors.newFixedThreadPool(Math.max(1, Runtime.getRuntime().availableProcessors() / 2));
        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.rotatedPositions.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) {
        if (this.isRotated(event.newState, event.pos, (class_1937)this.mc.field_1687)) {
            this.rotatedPositions.add(event.pos.method_10062());
        } else {
            this.rotatedPositions.remove(event.pos);
        }
    }

    private void scanChunk(class_2818 chunk) {
        class_1923 cpos = chunk.method_12004();
        int startX = cpos.method_8326();
        int startZ = cpos.method_8328();
        int min = Math.max(this.minY.get(), this.mc.field_1687.method_31607());
        int max = Math.min(this.maxY.get(), this.mc.field_1687.method_31600());
        for (int x = 0; x < 16; ++x) {
            for (int z = 0; z < 16; ++z) {
                for (int y = min; y <= max; ++y) {
                    class_2338 pos = new class_2338(startX + x, y, startZ + z);
                    class_2680 state = chunk.method_8320(pos);
                    if (!this.isRotated(state, pos, (class_1937)this.mc.field_1687)) continue;
                    this.rotatedPositions.add(pos.method_10062());
                }
            }
        }
    }

    private boolean isRotated(class_2680 state, class_2338 pos, class_1937 world) {
        boolean validBlock;
        if (state == null || state.method_26215()) {
            return false;
        }
        if (pos.method_10264() < this.minY.get() || pos.method_10264() > this.maxY.get()) {
            return false;
        }
        boolean bl = validBlock = this.includeRegular.get() != false && state.method_27852(class_2246.field_28888) || this.includeBricks.get() != false && state.method_27852(class_2246.field_28900) || this.includeTiles.get() != false && state.method_27852(class_2246.field_28896);
        if (!validBlock) {
            return false;
        }
        if (!state.method_28498((class_2769)class_2741.field_12496)) {
            return false;
        }
        if (state.method_11654((class_2769)class_2741.field_12496) == class_2350.class_2351.field_11052) {
            return false;
        }
        if (this.ignoreExposed.get().booleanValue() && world != null) {
            for (class_2350 dir : class_2350.values()) {
                class_2338 neighbor = pos.method_10093(dir);
                if (world.method_31606(neighbor)) {
                    return false;
                }
                class_2680 neighborState = world.method_8320(neighbor);
                if (!neighborState.method_26215() && neighborState.method_26225()) continue;
                return false;
            }
        }
        return true;
    }

    @EventHandler
    private void onRender(Render3DEvent event) {
        if (this.mc.field_1724 == null) {
            return;
        }
        this.boxColor.set(this.deepslateColor.get());
        this.lineColor.set(this.deepslateColor.get());
        this.lineColor.a = 255;
        int renderDistance = (Integer)this.mc.field_1690.method_42503().method_41753() * 16;
        double renderDistanceSq = (double)renderDistance * (double)renderDistance;
        for (class_2338 pos : this.rotatedPositions) {
            double distSq = this.mc.field_1724.method_5649((double)pos.method_10263() + 0.5, (double)pos.method_10264() + 0.5, (double)pos.method_10260() + 0.5);
            if (distSq > renderDistanceSq) continue;
            event.renderer.box(pos, this.boxColor, this.lineColor, this.deepslateShapeMode.get(), 0);
            if (!this.tracers.get().booleanValue()) continue;
            event.renderer.line(RenderUtils.center.field_1352, RenderUtils.center.field_1351, RenderUtils.center.field_1350, (double)pos.method_10263() + 0.5, (double)pos.method_10264() + 0.5, (double)pos.method_10260() + 0.5, this.lineColor);
        }
    }
}

