#include <stdio.h>
#include <string.h>

#include "fs_private.h"

#include "../core_runtime/core_runtime_private.h"

enum {
    FS_PAK_INFO_STRING_SIZE = 8192
};

static char fs_loadedPakChecksums[FS_PAK_INFO_STRING_SIZE];
static char fs_loadedPakNames[FS_PAK_INFO_STRING_SIZE];
static char fs_referencedPakChecksums[FS_PAK_INFO_STRING_SIZE];
static char fs_referencedPakNames[FS_PAK_INFO_STRING_SIZE];

/* NOT_FROM_ORIGINAL_SOURCE: shared source-level predicate for pak list output. */
static qboolean coduo_fs_pack_should_report_referenced(
    const pack_t *pack)
{
    uint32_t notedFlags;

    memcpy(&notedFlags, &pack->generalReference, sizeof(notedFlags));
    if (notedFlags != 0) {
        return qtrue;
    }

    if (Q_stricmpn(pack->pakGamename, "main", sizeof("main") - 1) == 0) {
        return qfalse;
    }

    if (Q_stricmpn(pack->pakGamename, fs_basegame->string,
                  (int)strlen(fs_basegame->string)) == 0) {
        return qfalse;
    }

    return qtrue;
}

const char *FS_LoadedPakChecksums(void)
{
    searchpath_t *searchpath;

    fs_loadedPakChecksums[0] = '\0';
    for (searchpath = FS_SearchpathHead(); searchpath != NULL;
         searchpath = FS_SearchpathNext(searchpath)) {
        if (searchpath->pack != NULL && searchpath->localized == qfalse) {
            pack_t *pack = searchpath->pack;

            Q_strcat(fs_loadedPakChecksums, sizeof(fs_loadedPakChecksums),
                     va("%i ", pack->checksum));
        }
    }

    return fs_loadedPakChecksums;
}

const char *FS_LoadedPakNames(void)
{
    searchpath_t *searchpath;

    fs_loadedPakNames[0] = '\0';
    for (searchpath = FS_SearchpathHead(); searchpath != NULL;
         searchpath = FS_SearchpathNext(searchpath)) {
        if (searchpath->pack != NULL && searchpath->localized == qfalse) {
            pack_t *pack = searchpath->pack;

            if (fs_loadedPakNames[0] != '\0') {
                Q_strcat(fs_loadedPakNames, sizeof(fs_loadedPakNames), " ");
            }
            Q_strcat(fs_loadedPakNames, sizeof(fs_loadedPakNames),
                     pack->pakBasename);
        }
    }

    return fs_loadedPakNames;
}

const char *FS_ReferencedPakChecksums(void)
{
    searchpath_t *searchpath;

    fs_referencedPakChecksums[0] = '\0';
    for (searchpath = FS_SearchpathHead(); searchpath != NULL;
         searchpath = FS_SearchpathNext(searchpath)) {
        if (searchpath->pack != NULL) {
            pack_t *pack = searchpath->pack;

            if (coduo_fs_pack_should_report_referenced(pack) != qfalse) {
                Q_strcat(fs_referencedPakChecksums,
                         sizeof(fs_referencedPakChecksums),
                         va("%i ", pack->checksum));
            }
        }
    }

    return fs_referencedPakChecksums;
}

const char *FS_ReferencedPakNames(void)
{
    searchpath_t *searchpath;

    fs_referencedPakNames[0] = '\0';
    for (searchpath = FS_SearchpathHead(); searchpath != NULL;
         searchpath = FS_SearchpathNext(searchpath)) {
        if (searchpath->pack != NULL) {
            pack_t *pack = searchpath->pack;

            if (coduo_fs_pack_should_report_referenced(pack) != qfalse) {
                if (fs_referencedPakNames[0] != '\0') {
                    Q_strcat(fs_referencedPakNames,
                             sizeof(fs_referencedPakNames), " ");
                }
                Q_strcat(fs_referencedPakNames,
                         sizeof(fs_referencedPakNames), pack->pakGamename);
                Q_strcat(fs_referencedPakNames,
                         sizeof(fs_referencedPakNames), "/");
                Q_strcat(fs_referencedPakNames,
                         sizeof(fs_referencedPakNames), pack->pakBasename);
            }
        }
    }

    return fs_referencedPakNames;
}
