#include "i18n.h"

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

/* Fixed-size, no heap allocation - deliberately (see i18n.h): keeps this
 * usable in a small embedded environment later, not just on desktop.
 * ~140 keys are shipped today (see engine/i18n/en.lang); this leaves
 * plenty of headroom for more languages/keys without growing the format. */
#define I18N_MAX_ENTRIES 320
#define I18N_MAX_KEY 48
#define I18N_MAX_VALUE 400

typedef struct {
  char key[I18N_MAX_KEY];
  char value[I18N_MAX_VALUE];
} I18nEntry;

static I18nEntry g_entries[I18N_MAX_ENTRIES];
static int g_entry_count = 0;

/* Bounded copy that's always null-terminated. Avoids strncpy() here,
 * which on glibc triggers a (harmless but noisy) -Wstringop-truncation
 * warning for exactly this "copy and then terminate" pattern. */
static void copy_bounded(char *dst, size_t dst_size, const char *src) {
  size_t len = strlen(src);
  if (len >= dst_size) len = dst_size - 1;
  memcpy(dst, src, len);
  dst[len] = '\0';
}

static void trim(char *s) {
  char *start = s;
  while (*start == ' ' || *start == '\t') start++;
  size_t len = strlen(start);
  while (len > 0 && (start[len - 1] == ' ' || start[len - 1] == '\t')) len--;
  memmove(s, start, len);
  s[len] = '\0';
}

bool i18n_load(const char *path) {
  FILE *f = fopen(path, "r");
  if (!f) return false;

  g_entry_count = 0;
  char line[I18N_MAX_KEY + I18N_MAX_VALUE + 4];
  while (fgets(line, sizeof line, f) && g_entry_count < I18N_MAX_ENTRIES) {
    line[strcspn(line, "\r\n")] = '\0';

    char *first = line;
    while (*first == ' ' || *first == '\t') first++;
    if (*first == '\0' || *first == '#') continue;

    char *eq = strchr(line, '=');
    if (!eq) continue;
    *eq = '\0';
    char *key = line;
    char *value = eq + 1;
    trim(key);
    trim(value);
    if (key[0] == '\0') continue;

    I18nEntry *entry = &g_entries[g_entry_count++];
    copy_bounded(entry->key, sizeof entry->key, key);
    copy_bounded(entry->value, sizeof entry->value, value);
  }
  fclose(f);
  return true;
}

const char *i18n_get(const char *key, const char *fallback) {
  for (int i = 0; i < g_entry_count; i++) {
    if (strcmp(g_entries[i].key, key) == 0) return g_entries[i].value;
  }
  return fallback;
}
