package zenith.zov.client.modules.impl.misc;

import com.darkmagician6.eventapi.EventTarget;
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import net.minecraft.block.AirBlock;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.MapColor;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import zenith.zov.base.events.impl.render.EventRender3D;
import zenith.zov.base.events.impl.server.EventPacket;
import zenith.zov.client.modules.api.Category;
import zenith.zov.client.modules.api.Module;
import zenith.zov.client.modules.api.ModuleAnnotation;
import zenith.zov.client.modules.api.setting.impl.BooleanSetting;
import zenith.zov.client.modules.api.setting.impl.NumberSetting;
import zenith.zov.utility.interfaces.IMinecraft;
import zenith.zov.utility.math.Timer;
import zenith.zov.utility.render.level.Render3DUtil;

@ModuleAnnotation(
    name = "BaseFinder",
    description = "finds bases",
    category = Category.MISC
)
public final class BaseFinder extends Module implements IMinecraft {
    private final NumberSetting range = new NumberSetting("Radius", 80.0F, 1.0F, 128.0F, 2.0F);
    private final NumberSetting time = new NumberSetting("Timer", 4.0F, 0.0F, 100.0F, 5.0F);
    private final BooleanSetting showOres = new BooleanSetting("Show Ores", true);
    private final BooleanSetting showChests = new BooleanSetting("Show Chests", true);
    private final BooleanSetting showSpawners = new BooleanSetting("Show Spawners", true);
    private final Timer timerUtil = new Timer();
    private final ExecutorService executor = Executors.newSingleThreadExecutor();
    private volatile boolean isStarted = true;
    private final List<BlockPos> foundBlocks = new ArrayList<>();
    public static BaseFinder INSTANCE = new BaseFinder();

    private BaseFinder() {
    }

    @Override
    public void onEnable() {
        this.timerUtil.setMillis(0L);
        this.isStarted = true;
        super.onEnable();
    }

    @Override
    public void onDisable() {
        this.isStarted = false;
        synchronized (this.foundBlocks) {
            this.foundBlocks.clear();
        }

        super.onDisable();
    }

    @EventTarget
    public void render(EventRender3D eventRender3D) {
        if (mc.player != null && mc.world != null) {
            if (this.timerUtil.finished(this.time.getCurrent() * 1000.0F) && this.isStarted) {
                this.executor.submit(this::scan);
                this.timerUtil.reset();
            }

            synchronized (this.foundBlocks) {
                for (BlockPos pos : this.foundBlocks) {
                    Block block = mc.world.getBlockState(pos).getBlock();
                    int color;
                    if (block == Blocks.DIAMOND_ORE || block == Blocks.DEEPSLATE_DIAMOND_ORE) {
                        color = Color.cyan.getRGB();
                    } else if (block == Blocks.GOLD_ORE || block == Blocks.DEEPSLATE_GOLD_ORE || block == Blocks.NETHER_GOLD_ORE) {
                        color = -10496;
                    } else if (block == Blocks.EMERALD_ORE || block == Blocks.DEEPSLATE_EMERALD_ORE) {
                        color = -16711859;
                    } else if (block == Blocks.IRON_ORE || block == Blocks.DEEPSLATE_IRON_ORE) {
                        color = -2763307;
                    } else if (block == Blocks.REDSTONE_ORE || block == Blocks.DEEPSLATE_REDSTONE_ORE) {
                        color = -65536;
                    } else if (block == Blocks.ANCIENT_DEBRIS) {
                        color = -1;
                    } else if (block == Blocks.CHEST || block == Blocks.ENDER_CHEST) {
                        color = -7650029;
                    } else if (block == Blocks.SPAWNER) {
                        color = -7667712;
                    } else if (block == Blocks.END_PORTAL_FRAME) {
                        color = -11861886;
                    } else {
                        MapColor mapColor = block.getDefaultMapColor();
                        color = new Color(mapColor.color).getRGB();
                    }

                    this.drawBox(pos, color);
                }
            }
        }
    }

    @EventTarget
    public void packer(EventPacket eventPacket) {
    }

    public void drawBox(BlockPos blockPos, int start) {
        Render3DUtil.drawBox(new Box(blockPos), start, 1.0F);
    }

    private void scan() {
        if (mc.player != null && mc.world != null) {
            ArrayList<BlockPos> blocks = new ArrayList<>();
            int startX = (int)Math.floor(mc.player.getX() - (double)this.range.getCurrent());
            int endX = (int)Math.ceil(mc.player.getX() + (double)this.range.getCurrent());
            int startY = mc.world.getBottomY() + 1;
            int endY = mc.world.getTopYInclusive();
            int startZ = (int)Math.floor(mc.player.getZ() - (double)this.range.getCurrent());
            int endZ = (int)Math.ceil(mc.player.getZ() + (double)this.range.getCurrent());

            for (int x = startX; x <= endX; x++) {
                for (int y = startY; y <= endY; y++) {
                    for (int z = startZ; z <= endZ; z++) {
                        if (!this.isStarted) {
                            return;
                        }

                        BlockPos pos = new BlockPos(x, y, z);
                        Block block = mc.world.getBlockState(pos).getBlock();
                        if (!(block instanceof AirBlock) && this.isValuableBlock(block)) {
                            blocks.add(pos);
                        }
                    }
                }
            }

            synchronized (this.foundBlocks) {
                this.foundBlocks.clear();
                this.foundBlocks.addAll(blocks);
            }
        }
    }

    private boolean isValuableBlock(Block block) {
        if (!this.showOres.isEnabled()
            || block != Blocks.DIAMOND_ORE
                && block != Blocks.DEEPSLATE_DIAMOND_ORE
                && block != Blocks.GOLD_ORE
                && block != Blocks.DEEPSLATE_GOLD_ORE
                && block != Blocks.NETHER_GOLD_ORE
                && block != Blocks.EMERALD_ORE
                && block != Blocks.DEEPSLATE_EMERALD_ORE
                && block != Blocks.IRON_ORE
                && block != Blocks.DEEPSLATE_IRON_ORE
                && block != Blocks.REDSTONE_ORE
                && block != Blocks.DEEPSLATE_REDSTONE_ORE
                && block != Blocks.ANCIENT_DEBRIS) {
            return !this.showChests.isEnabled() || block != Blocks.CHEST && block != Blocks.ENDER_CHEST
                ? this.showSpawners.isEnabled() && (block == Blocks.SPAWNER || block == Blocks.END_PORTAL_FRAME)
                : true;
        } else {
            return true;
        }
    }
}
