#include "xbox_region.h"

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

#define XBOX_REGION_KNOWN_MASK \
    (XB_REGION_US_CANADA | XB_REGION_JAPAN | \
     XB_REGION_EUROPE_AU_NZ | XB_REGION_REST_OF_WORLD | \
     XB_REGION_MANUFACTURING)

static void xbox_region_append(char *output,
                               size_t output_size,
                               const char *text,
                               int *have_text)
{
    size_t used;

    if (!output || output_size == 0 || !text || !have_text)
        return;

    used = strlen(output);
    if (used >= output_size - 1)
        return;

    if (*have_text) {
        snprintf(output + used, output_size - used, "; ");
        used = strlen(output);
        if (used >= output_size - 1)
            return;
    }

    snprintf(output + used, output_size - used, "%s", text);
    *have_text = 1;
}

int xbox_region_format(uint32_t mask, char *output, size_t output_size)
{
    uint32_t execution_mask;
    uint32_t unknown_mask;
    int have_text;
    char unknown[32];

    if (!output || output_size == 0)
        return 0;

    output[0] = '\0';
    have_text = 0;
    execution_mask = mask & 0x7fffffffU;

    if (execution_mask == 0x7fffffffU) {
        xbox_region_append(output, output_size, "Region Free", &have_text);
    } else if (execution_mask == 0U) {
        xbox_region_append(output, output_size, "None (Locked)", &have_text);
    } else {
        if (mask & XB_REGION_US_CANADA)
            xbox_region_append(output, output_size, "North America", &have_text);
        if (mask & XB_REGION_JAPAN)
            xbox_region_append(output, output_size, "Japan", &have_text);
        if (mask & XB_REGION_EUROPE_AU_NZ)
            xbox_region_append(output, output_size,
                               "Europe/Australia/New Zealand", &have_text);
        if (mask & XB_REGION_REST_OF_WORLD)
            xbox_region_append(output, output_size,
                               "Rest of World", &have_text);
    }

    if (mask & XB_REGION_MANUFACTURING)
        xbox_region_append(output, output_size, "Manufacturing", &have_text);

    unknown_mask = mask & ~((uint32_t)XBOX_REGION_KNOWN_MASK);
    if (execution_mask != 0x7fffffffU && unknown_mask != 0U) {
        snprintf(unknown, sizeof(unknown), "Unknown flags 0x%08x",
                 unknown_mask);
        xbox_region_append(output, output_size, unknown, &have_text);
    }

    return 1;
}
