// #include <utils/util.h>
// #include "tools.h"
#include <storage/sd.h>
#include "../fs/readers/folderReader.h"
#include "../fs/fstypes.h"
#include "../fs/fscopy.h"
#include <utils/sprintf.h>
#include <stdlib.h>
#include <string.h>
#include "../gfx/gfx.h"
#include "../gfx/gfxutils.h"
#include "../gfx/menu.h"
#include "../hid/hid.h"
// #include "utils.h"
#include "../utils/utils.h"
#include "../fs/fsutils.h"

#include <unistd.h>
#include <sys/types.h>

#include "../warmboot/warmboot_extractor.h"
// #include <dirent.h>
// #include <stdio.h>
#include <string.h>
#include <sys/stat.h>

void _DeleteFileSimple(char *thing){
    //char *thing = CombinePaths(path, entry.name);
    int res = f_unlink(thing);
    if (res)
        DrawError(newErrCode(res));
    free(thing);
}
void _RenameFileSimple(char *sourcePath, char *destPath){
    int res = f_rename(sourcePath, destPath);
    if (res){
        DrawError(newErrCode(res));
    }
}
ErrCode_t _FolderDelete(const char *path){
    int res = 0;
    ErrCode_t ret = newErrCode(0);
    u32 x, y;
    gfx_con_getpos(&x, &y);
    Vector_t fileVec = ReadFolder(path, &res);
    if (res){
        ret = newErrCode(res);
    }
    else {
        vecDefArray(FSEntry_t *, fs, fileVec);
        for (int i = 0; i < fileVec.count && !ret.err; i++){
            char *temp = CombinePaths(path, fs[i].name);
            if (fs[i].isDir){
                ret = _FolderDelete(temp);
            }
            else {
                res = f_unlink(temp);
                if (res){
                    ret = newErrCode(res);
                }             
            }
            free(temp);
        }
    }
    if (!ret.err){
        res = f_unlink(path);
        if (res)
            ret = newErrCode(res);
    }
    clearFileVector(&fileVec);
    return ret;
}
int _StartsWith(const char *a, const char *b)
{
   if(strncmp(a, b, strlen(b)) == 0) return 1;
   return 0;
}

int listdir(char *path, u32 hos_folder, int *deleted_count)
{
   	FRESULT res;
	DIR dir;
	u32 dirLength = 0;
	static FILINFO fno;

    // Open directory.
	res = f_opendir(&dir, path);
	if (res != FR_OK)
		return res;

    dirLength = strlen(path);
	for (;;)
	{
		// Clear file or folder path.
		path[dirLength] = 0;
		// Read a directory item.
		res = f_readdir(&dir, &fno);
		// Break on error or end of dir.
		if (res != FR_OK || fno.fname[0] == 0)
			break;
		// Skip official Nintendo dir if started from root.
		if (!hos_folder && !strcmp(fno.fname, "Nintendo"))
			continue;

		// Set new directory or file.
		memcpy(&path[dirLength], "/", 1);
		memcpy(&path[dirLength + 1], fno.fname, strlen(fno.fname) + 1);

        // Is it a directory?
		if (fno.fattrib & AM_DIR)
		{
            if (
                strcmp(fno.fname, ".Trash") == 0 ||
                strcmp(fno.fname, ".Trashes") == 0 ||
                strcmp(fno.fname, ".DS_Store") == 0 ||
                strcmp(fno.fname, ".Spotlight-V100")  == 0 ||
                strcmp(fno.fname, ".apDisk")  == 0 ||
                strcmp(fno.fname, ".VolumeIcon.icns")  == 0 ||
                strcmp(fno.fname, ".fseventsd")  == 0 ||
                strcmp(fno.fname, ".TemporaryItems")  == 0
            ) {
                _FolderDelete(path);
                if (deleted_count) (*deleted_count)++;
            }
            else {
                // Only recurse into directories that were not deleted.
                listdir(path, 0, deleted_count);
            }
			if (res != FR_OK)
				break;
		} else {
            if (
                strcmp(fno.fname, ".DS_Store") == 0 ||
                strcmp(fno.fname, ".Spotlight-V100")  == 0 ||
                strcmp(fno.fname, ".apDisk")  == 0 ||
                strcmp(fno.fname, ".VolumeIcon.icns")  == 0 ||
                strcmp(fno.fname, ".fseventsd")  == 0 ||
                strcmp(fno.fname, ".TemporaryItems")  == 0 ||
                _StartsWith(fno.fname, "._")
            ) {
                res = f_unlink(path);
                if (res)
                    DrawError(newErrCode(res));
                if (deleted_count) (*deleted_count)++;
            }
        }
	}
    f_closedir(&dir);
	return res;
}

int _fix_attributes(char *path, u32 *total, u32 hos_folder, u32 check_first_run){
	FRESULT res;
	DIR dir;
	u32 dirLength = 0;
	static FILINFO fno;

	if (check_first_run)
	{
		// Read file attributes.
		res = f_stat(path, &fno);
		if (res != FR_OK)
			return res;

		// Check if archive bit is set.
		if (fno.fattrib & AM_ARC)
		{
			*(u32 *)total = *(u32 *)total + 1;
			f_chmod(path, 0, AM_ARC);
		}
	}

	// Open directory.
	res = f_opendir(&dir, path);
	if (res != FR_OK)
		return res;

	dirLength = strlen(path);
	for (;;)
	{
		// Clear file or folder path.
		path[dirLength] = 0;

		// Read a directory item.
		res = f_readdir(&dir, &fno);

		// Break on error or end of dir.
		if (res != FR_OK || fno.fname[0] == 0)
			break;

		// Skip official Nintendo dir if started from root.
		if (!hos_folder && !strcmp(fno.fname, "Nintendo"))
			continue;

		// Set new directory or file.
		memcpy(&path[dirLength], "/", 1);
		memcpy(&path[dirLength + 1], fno.fname, strlen(fno.fname) + 1);

		// Check if archive bit is set.
		if (fno.fattrib & AM_ARC)
		{
			*total = *total + 1;
			f_chmod(path, 0, AM_ARC);
		}

		// Is it a directory?
		if (fno.fattrib & AM_DIR)
		{
			// Set archive bit to NCA folders.
			if (hos_folder && !strcmp(fno.fname + strlen(fno.fname) - 4, ".nca"))
			{
				*total = *total + 1;
				f_chmod(path, AM_ARC, AM_ARC);
			}

			// Enter the directory.
			res = _fix_attributes(path, total, hos_folder, 0);
			if (res != FR_OK)
				break;
		}
	}

	f_closedir(&dir);

	return res;
}


void m_entry_fixArchiveBit(u32 type){
    gfx_clearscreen();
    gfx_printf("\n\n-- Behebe Archive Bit\n\n");

    char path[256];
	char label[16];

	u32 total = 0;
	if (sd_mount())
	{
		switch (type)
		{
		case 0:
			strcpy(path, "/");
			strcpy(label, "SD-Karte");
			break;
		case 1:
		default:
			strcpy(path, "/Nintendo");
			strcpy(label, "Nintendo Ordner");
			break;
		}

		gfx_printf("Durchlaufe alle %s Dateien!\nDas kann einige Zeit dauern...\n\n", label);
		_fix_attributes(path, &total, type, type);
		gfx_printf("%kAnzahl reparierter Archiv bits: %d!%k", 0xFF96FF00, total, 0xFFCCCCCC);
		
        gfx_printf("\n\n Fertig! Druecke eine Taste um zurueckzukehren");
        hidWait();
	}
}


static void _fixAMSErrorFolder(const char *titleId, const char *label){
    gfx_clearscreen();
    gfx_printf("\n\n-- Fix Fehlercode %s --\n\n", label);
    if (!sd_mount()) {
        gfx_printf("SD-Karte konnte nicht gemountet werden.\n");
        hidWait();
        return;
    }
    char *path = CpyStr("sd:/atmosphere/contents");
    char *full = CombinePaths(path, titleId);
    free(path);
    if (FileExists(full)) {
        gfx_printf("Entferne Ordner %s ...\n", titleId);
        FolderDelete(full);
        gfx_printf("Ordner erfolgreich geloescht.\n");
    } else {
        gfx_printf("Ordner %s nicht gefunden (evtl. bereits behoben).\n", titleId);
    }
    free(full);
    gfx_printf("\n\n Fertig! Druecke eine Taste um zurueckzukehren");
    hidWait();
}

void m_entry_fixAMSError_4200(void){
    _fixAMSErrorFolder("4200000000000010", "4200000000000010");
}

void m_entry_fixAMSError_6900(void){
    _fixAMSErrorFolder("690000000000000D", "690000000000000D");
}

void m_entry_fixAMSError_BD00(void){
    _fixAMSErrorFolder("010000000000BD00", "010000000000BD00");
}

static int _deleteTheme(char* basePath, char* folderId){
    int removed = 0;
    char *path = CombinePaths(basePath, folderId);
    if (FileExists(path)) {
        gfx_printf("-- Theme gefunden: %s\n", path);
        FolderDelete(path);
        removed = 1;
    }
    free(path);
    return removed;
}

void m_entry_deleteInstalledThemes(){
    gfx_clearscreen();
    gfx_printf("\n\n-- Loesche installierte Themes.\n\n");
    int count = 0;
    count += _deleteTheme("sd:/atmosphere/contents", "0100000000001000");
    count += _deleteTheme("sd:/atmosphere/contents", "0100000000001007");
    count += _deleteTheme("sd:/atmosphere/contents", "0100000000001013");

    if (count > 0)
        gfx_printf("\n%d Theme(s) geloescht.\n", count);
    else
        gfx_printf("\nKeine installierten Themes gefunden.\n");
    gfx_printf("\n\n Fertig! Druecke eine Taste um zurueckzukehren");
    hidWait();
}

void m_entry_deleteBootFlags(){
    gfx_clearscreen();
    gfx_printf("\n\n-- Automatisches starten der sysmodule deaktivieren.\n\n");
    char *storedPath = CpyStr("sd:/atmosphere/contents");
    int readRes = 0;
    int count = 0;
    Vector_t fileVec = ReadFolder(storedPath, &readRes);
    if (readRes){
        clearFileVector(&fileVec);
        free(storedPath);
        DrawError(newErrCode(readRes));
    } else {
        vecDefArray(FSEntry_t*, fsEntries, fileVec);
        for (int i = 0; i < fileVec.count; i++){
            char *suf = "/flags/boot2.flag";
            char *subPath = CombinePaths(storedPath, fsEntries[i].name);
            char *flagPath = CombinePaths(subPath, suf);
            free(subPath);
            if (FileExists(flagPath)) {
                gfx_printf("Loesche: %s\n", flagPath);
                _DeleteFileSimple(flagPath);
                count++;
            } else {
                free(flagPath);
            }
        }
        clearFileVector(&fileVec);
        free(storedPath);
    }
    if (count > 0)
        gfx_printf("\n%d Boot-Flag(s) geloescht.\n", count);
    else if (!readRes)
        gfx_printf("\nKeine Boot-Flags gefunden.\n");
    gfx_printf("\n\n Fertig! Druecke eine Taste um zurueckzukehren");
    hidWait();
}



void m_entry_fixMacSpecialFolders(){
    gfx_clearscreen();
    gfx_printf("\n\n-- Mac-Ordner reparieren (dies kann ein wenig dauern, bitte warten.)\n\n");
    int deleted = 0;
    char path[1024];
    strcpy(path, "sd:/");
    listdir(path, 0, &deleted);
    if (deleted > 0)
        gfx_printf("\n%d Mac-Datei(en)/Ordner entfernt.\n", deleted);
    else
        gfx_printf("\nKeine Mac-Sonderdateien oder -ordner gefunden.\n");
    gfx_printf("\n\n Fertig! Druecke eine Taste um zurueckzukehren");
    hidWait();
}

static u32 _hex_nibble_lower(char c)
{
    if (c >= '0' && c <= '9')
        return (u32)(c - '0');
    if (c >= 'a' && c <= 'f')
        return (u32)(c - 'a' + 10);
    return 0xFFFFFFFFu;
}

static bool _parse_wb_filename_lower(const char *fname, u32 *fuse_out)
{
    // Expected: wb_xx.bin where xx is lowercase hex (exactly 2 chars).
    // Example: wb_16.bin
    if (!fname || !fuse_out)
        return false;

    // Length check: "wb_" + 2 + ".bin" = 3 + 2 + 4 = 9
    if (strlen(fname) != 9)
        return false;
    if (strncmp(fname, "wb_", 3) != 0)
        return false;
    if (fname[5] != '.')
        return false;
    if (strncmp(fname + 6, "bin", 3) != 0)
        return false;

    u32 hi = _hex_nibble_lower(fname[3]);
    u32 lo = _hex_nibble_lower(fname[4]);
    if (hi == 0xFFFFFFFFu || lo == 0xFFFFFFFFu)
        return false;

    *fuse_out = (hi << 4) | lo;
    return true;
}

static void _rstrip(char *s)
{
    if (!s)
        return;
    int n = (int)strlen(s);
    while (n > 0)
    {
        char c = s[n - 1];
        if (c == '\n' || c == '\r' || c == ' ' || c == '\t')
            s[--n] = 0;
        else
            break;
    }
}

static char *_ltrim(char *s)
{
    if (!s)
        return s;
    while (*s == ' ' || *s == '\t')
        s++;
    return s;
}

static bool _read_line_no_nl(FIL *fp, char *out, u32 out_sz)
{
    if (!fp || !out || out_sz < 2)
        return false;

    u32 idx = 0;
    BYTE b;
    UINT br = 0;

    // Return false on immediate EOF.
    for (;;)
    {
        if (idx >= out_sz - 1)
            break;

        FRESULT res = f_read(fp, &b, 1, &br);
        if (res != FR_OK || br == 0)
            break;

        if (b == '\n')
            break;
        if (b == '\r')
            continue;

        out[idx++] = (char)b;
    }

    out[idx] = 0;
    return idx > 0 || br != 0;
}

static bool _ini_section_exists(const char *ini_path, const char *section_name)
{
    FIL fp;
    if (f_open(&fp, ini_path, FA_READ) != FR_OK)
        return false;

    char line[256];
    bool found = false;

    while (_read_line_no_nl(&fp, line, sizeof(line)))
    {
        char *t = _ltrim(line);
        if (*t == '[')
        {
            char *end = strchr(t, ']');
            if (end)
            {
                *end = 0;
                if (!strcmp(t + 1, section_name))
                {
                    found = true;
                    break;
                }
                *end = ']';
            }
        }
    }

    f_close(&fp);
    return found;
}

static bool _ini_section_warmboot_is(const char *ini_path, const char *section_name, const char *warmboot_value_rel)
{
    FIL fp;
    if (f_open(&fp, ini_path, FA_READ) != FR_OK)
        return false;

    char line[256];
    bool in_section = false;
    bool is_set = false;

    while (_read_line_no_nl(&fp, line, sizeof(line)))
    {
        char *t = _ltrim(line);
        if (*t == '[')
        {
            char *end = strchr(t, ']');
            if (end)
            {
                *end = 0;
                in_section = !strcmp(t + 1, section_name);
                *end = ']';
            }
            continue;
        }

        if (!in_section)
            continue;

        char *k = _ltrim(line);
        if (strncmp(k, "warmboot", 8) != 0)
            continue;

        // Ensure this is the "warmboot" key (not warmboot2/etc), allowing whitespace before '='.
        char *p = k + 8;
        while (*p == ' ' || *p == '\t')
            p++;
        if (*p != '=')
            continue;
        p++;
        p = _ltrim(p);
        _rstrip(p);

        if (!strcmp(p, warmboot_value_rel))
        {
            is_set = true;
            break;
        }
    }

    f_close(&fp);
    return is_set;
}

static bool _ini_update_section_warmboot(const char *ini_path, const char *section_name, const char *warmboot_value_rel)
{
    char tmp_path[128];
    u32 len = strlen(ini_path);
    if (len + 4 >= sizeof(tmp_path))
        return false;
    strcpy(tmp_path, ini_path);
    strcat(tmp_path, ".tmp");

    FIL in_fp;
    FIL out_fp;
    if (f_open(&in_fp, ini_path, FA_READ) != FR_OK)
        return false;
    if (f_open(&out_fp, tmp_path, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK)
    {
        f_close(&in_fp);
        return false;
    }

    char line[256];
    bool in_section = false;
    bool warmboot_seen = false;
    bool wrote_any = false;
    // Buffer trailing empty lines in the target section so the inserted/updated
    // warmboot=... line stays directly after the last non-empty line.
    #define MAX_PENDING_BLANKS 32
    char pending_blanks[MAX_PENDING_BLANKS][256];
    u32 pending_blank_count = 0;

    while (_read_line_no_nl(&in_fp, line, sizeof(line)))
    {
        char *t = _ltrim(line);

        // Section header?
        if (*t == '[')
        {
            if (in_section && !warmboot_seen)
            {
                f_printf(&out_fp, "warmboot=%s\n", warmboot_value_rel);
                warmboot_seen = true;
                wrote_any = true;
            }

            // Flush buffered empty lines after warmboot, so they don't split it.
            for (u32 i = 0; i < pending_blank_count; i++)
            {
                f_printf(&out_fp, "%s\n", pending_blanks[i]);
            }
            pending_blank_count = 0;

            char *end = strchr(t, ']');
            if (end)
            {
                *end = 0;
                in_section = !strcmp(t + 1, section_name);
                *end = ']';
            }

            f_printf(&out_fp, "%s\n", line);
            wrote_any = true;
            continue;
        }

        if (in_section)
        {
            char *k = _ltrim(line);
            if (strncmp(k, "warmboot", 8) == 0)
            {
                // Replace existing warmboot=... line inside the section.
                // Allow whitespace between key and '='.
                char *p = k + 8;
                while (*p == ' ' || *p == '\t')
                    p++;
                if (*p == '=')
                {
                    // Keep the buffered empty lines where the original warmboot key appeared.
                    for (u32 i = 0; i < pending_blank_count; i++)
                    {
                        f_printf(&out_fp, "%s\n", pending_blanks[i]);
                        wrote_any = true;
                    }
                    pending_blank_count = 0;

                    f_printf(&out_fp, "warmboot=%s\n", warmboot_value_rel);
                    warmboot_seen = true;
                    wrote_any = true;
                    continue;
                }
            }
        }

        // If we're in the target section and warmboot isn't present yet, buffer empty lines
        // so warmboot will not be separated from the last non-empty entry.
        if (in_section && !warmboot_seen)
        {
            if (*t == 0)
            {
                if (pending_blank_count < MAX_PENDING_BLANKS)
                {
                    strncpy(pending_blanks[pending_blank_count], line, 255);
                    pending_blanks[pending_blank_count][255] = 0;
                    pending_blank_count++;
                }
                else
                {
                    for (u32 i = 0; i < pending_blank_count; i++)
                    {
                        f_printf(&out_fp, "%s\n", pending_blanks[i]);
                        wrote_any = true;
                    }
                    pending_blank_count = 0;

                    f_printf(&out_fp, "%s\n", line);
                    wrote_any = true;
                }
                continue;
            }

            // Non-empty line: flush buffered blanks first.
            for (u32 i = 0; i < pending_blank_count; i++)
            {
                f_printf(&out_fp, "%s\n", pending_blanks[i]);
                wrote_any = true;
            }
            pending_blank_count = 0;
        }

        f_printf(&out_fp, "%s\n", line);
        wrote_any = true;
    }

    if (in_section && !warmboot_seen)
    {
        f_printf(&out_fp, "warmboot=%s\n", warmboot_value_rel);
        wrote_any = true;
    }

    // Flush trailing empty lines at EOF (after warmboot) if any.
    for (u32 i = 0; i < pending_blank_count; i++)
    {
        f_printf(&out_fp, "%s\n", pending_blanks[i]);
        wrote_any = true;
    }
    pending_blank_count = 0;

    f_close(&in_fp);
    f_close(&out_fp);

    if (!wrote_any)
        return false;

    // Replace original with temp.
    f_unlink(ini_path);
    f_rename(tmp_path, ini_path);
    return true;
}

void m_entry_fixMarikoWarmbootSleep(void)
{
    gfx_clearscreen();
    gfx_printf("\n\n-- Mariko Sleep Fix (Warmboot) --\n\n");

    char warmboot_rel[64] = {0};
    bool warmboot_generated = false;

    // 1) Generate a fresh warmboot for the currently burnt fuses.
    //    Then we directly update the INI using that result.
    gfx_printf("Erzeuge neuen Warmboot Cache...\n\n");

    warmboot_info_t wb_info;
    wb_extract_error_t wberr = extract_warmboot_from_pkg1_ex(&wb_info);
    if (wberr == WB_SUCCESS)
    {
        char warmboot_sd_path[128];
        get_warmboot_path(warmboot_sd_path, sizeof(warmboot_sd_path), wb_info.burnt_fuses);

        if (save_warmboot_to_sd(&wb_info, warmboot_sd_path))
        {
            s_printf(warmboot_rel, "warmboot_mariko/wb_%02x.bin", wb_info.burnt_fuses);
            warmboot_generated = true;
            gfx_printf("Neues warmboot: %s\n\n", warmboot_rel);
        }
        else
        {
            gfx_printf("Speichern auf SD fehlgeschlagen.\n\n");
        }
    }
    else
    {
        gfx_printf("Warmboot Extraktion fehlgeschlagen: %s\n\n", wb_error_to_string(wberr));
    }

    if (wb_info.data)
        free(wb_info.data);

    // 2) Fallback: pick the newest cached wb_xx.bin from sd:/warmboot_mariko.
    if (!warmboot_generated)
    {
        const char *wb_dir = "sd:/warmboot_mariko";

        DIR dir;
        static FILINFO fno;
        if (f_opendir(&dir, wb_dir) != FR_OK)
        {
            gfx_printf("Ordner nicht gefunden: %s\n\n", wb_dir);
            gfx_printf("Bitte erst Warmboot-Extractor ausfuehren:\n");
            gfx_printf("https://github.com/sthetix/Warmboot-Extractor\n\n");
            gfx_printf("Druecke eine Taste um zurueckzukehren");
            hidWait();
            return;
        }

        u32 best_fuse = 0;
        u32 best_ts = 0;
        bool found_any = false;

        for (;;)
        {
            FRESULT res = f_readdir(&dir, &fno);
            if (res != FR_OK || fno.fname[0] == 0)
                break;
            if (fno.fattrib & AM_DIR)
                continue;

            u32 fuse = 0;
            if (!_parse_wb_filename_lower(fno.fname, &fuse))
                continue;

            u32 ts = ((u32)fno.fdate << 16) | (u32)fno.ftime;
            if (!found_any || fuse > best_fuse || (fuse == best_fuse && ts > best_ts))
            {
                best_fuse = fuse;
                best_ts = ts;
                found_any = true;
            }
        }

        f_closedir(&dir);

        if (!found_any)
        {
            gfx_printf("Keine passenden Dateien gefunden in %s:\n", wb_dir);
            gfx_printf("wb_xx.bin (xx = lowercase hex fuse)\n\n");
            gfx_printf("Bitte Warmboot-Extractor ausfuehren:\n");
            gfx_printf("https://github.com/sthetix/Warmboot-Extractor\n\n");
            gfx_printf("Druecke eine Taste um zurueckzukehren");
            hidWait();
            return;
        }

        s_printf(warmboot_rel, "warmboot_mariko/wb_%02x.bin", best_fuse);
        gfx_printf("Neuestes warmboot: %s\n\n", warmboot_rel);
    }

    const char *ini_path = "sd:/bootloader/hekate_ipl.ini";
    const char *preferred_section = "CFW-EmuMMC";

    if (!_ini_section_exists(ini_path, preferred_section))
    {
        // Fallback: show a section chooser if CFW-EmuMMC doesn't exist.
        gfx_printf("Section %s nicht gefunden.\n", preferred_section);
        gfx_printf("Bitte waehle eine INI section.\n\n");

        // Collect section names.
        #define MAX_INI_SECTIONS 20
        char section_names[MAX_INI_SECTIONS][64];
        int section_count = 0;

        FIL ini_fp;
        if (f_open(&ini_fp, ini_path, FA_READ) != FR_OK)
        {
            gfx_printf("Datei nicht gefunden: %s\n", ini_path);
            gfx_printf("Druecke eine Taste um zurueckzukehren");
            hidWait();
            return;
        }

        char line[256];
        while (_read_line_no_nl(&ini_fp, line, sizeof(line)))
        {
            char *t = _ltrim(line);
            if (*t != '[')
                continue;
            char *end = strchr(t, ']');
            if (!end)
                continue;

            *end = 0;
            char *name = t + 1;

            name = _ltrim(name);
            _rstrip(name);

            // Skip empty section headers like "[]"
            if (!*name)
            {
                *end = ']';
                continue;
            }

            if (strcmp(name, "config") && section_count < MAX_INI_SECTIONS)
            {
                strncpy(section_names[section_count], name, 63);
                section_names[section_count][63] = 0;
                section_count++;
            }
            *end = ']';
        }
        f_close(&ini_fp);

        if (section_count <= 0)
        {
            gfx_printf("Keine INI sections gefunden in %s.\n", ini_path);
            gfx_printf("Druecke eine Taste um zurueckzukehren");
            hidWait();
            return;
        }

        MenuEntry_t entries[MAX_INI_SECTIONS + 1];
        memset(entries, 0, sizeof(entries));
        entries[0].optionUnion = COLORTORGB(COLOR_WHITE);
        entries[0].name = "<- Zurueck";
        for (int i = 0; i < section_count; i++)
        {
            entries[i + 1].optionUnion = COLORTORGB(COLOR_YELLOW);
            entries[i + 1].name = section_names[i];
        }

        Vector_t ent = vecFromArray(entries, section_count + 1, sizeof(MenuEntry_t));
        int sel = newMenu(&ent, 0, 79, 20, ENABLEB | ALWAYSREDRAW, section_count + 1);
        // newMenu returns 0 for "<- Back" and also when the user presses B.
        if (sel == 0)
            return;
        if (sel < 0 || sel > section_count)
            return;

        const char *selected_section = section_names[sel - 1];
        // Continue below with chosen section.
        // Clear and re-print banner so the header stays visible (success/fail).
        gfx_clearscreen();
        gfx_printf("\n\n-- Mariko Sleep Fix (Warmboot) --\n\n");

        if (_ini_section_warmboot_is(ini_path, selected_section, warmboot_rel))
        {
            gfx_printf("\nwarmboot=%s existiert schon in [%s].\n", warmboot_rel, selected_section);
            gfx_printf("Druecke eine Taste um zurueckzukehren");
            hidWait();
            return;
        }

        _ini_update_section_warmboot(ini_path, selected_section, warmboot_rel);
        gfx_printf("\nAktualisiert in [%s].\n", selected_section);
        gfx_printf("Druecke eine Taste um zurueckzukehren");
        hidWait();
        return;
    }

    // Preferred path: always update CFW-EmuMMC directly.
    if (_ini_section_warmboot_is(ini_path, preferred_section, warmboot_rel))
    {
        gfx_printf("\nwarmboot=%s existiert schon in [%s].\n", warmboot_rel, preferred_section);
        gfx_printf("Druecke eine Taste um zurueckzukehren");
        hidWait();
        return;
    }

    _ini_update_section_warmboot(ini_path, preferred_section, warmboot_rel);
    gfx_printf("\nAktualisiert in [%s].\n", preferred_section);
    gfx_printf("Druecke eine Taste um zurueckzukehren");
    hidWait();
}

void m_entry_stillNoBootInfo(){
    gfx_clearscreen();
    gfx_printf("\n\n-- Meine Switch startet immer noch nicht.\n\n");

    gfx_printf("%kSteckt eine Spiel-Cardrige im Slot?\n", COLOR_WHITE);
    gfx_printf("Entferne sie und starte neu.\n\n");

    gfx_printf("%kHast du vor kurzem Atmosphere/OmniNX aktualisiert?\n", COLOR_WHITE);
    gfx_printf("Stecke die SD-Karte in deinen PC, hol das neue Paket vom NiklasCFW Discord-Server und entpacke die .zip Datei auf deine SD-Karte und ueberschreibe alle Dateien.\nDanach kannst du den OmniNX-Installer-Payload ausfuehren.\n\n");

    gfx_printf("%kHast du eine neue SD-Karte gekauft?\n", COLOR_WHITE);
    gfx_printf("Vergewissere dich das es keine fake/SanDisk Karte ist.\n\n");

    gfx_printf("\n\n Druecke eine Taste um zurueckzukehren");
    hidWait();
}

void m_entry_ViewCredits(){
    gfx_clearscreen();
    gfx_printf("\nAllgemeinerProblemLoeser %d.%d.%d\nVon Team Neptune - (NiklasCFW Fork - Uebersetzt von Switch Bros.)\n\nBasierend auf TegraExplorer von SuchMemeManySkill,\nLockpick_RCM & Hekate, von shchmue & CTCaer\n\n\n", APL_VER_MJ, APL_VER_MN, APL_VER_BF);
    hidWait();
}

void m_entry_fixAll(){
    gfx_clearscreen();
    m_entry_deleteBootFlags();
    m_entry_deleteInstalledThemes();

    m_entry_stillNoBootInfo();
}
