#include "cvm_core.h"
#include <stdlib.h>
#include <string.h>

/* --------------------------- 通用字符串映射 --------------------------- */
static char *dup_str(const char *s) {
    size_t n = strlen(s) + 1;
    char *p = (char *)malloc(n);
    if (!p) abort();
    memcpy(p, s, n);
    return p;
}

static unsigned long long hash_str(const char *s) {
    unsigned long long h = 1469598103934665603ULL; /* FNV-1a 64 */
    for (; *s; ++s) {
        h ^= (unsigned char)*s;
        h *= 1099511628211ULL;
    }
    return h;
}

void map_init(Map *m) {
    m->cap = 64;
    m->count = 0;
    m->buckets = (MapNode **)calloc((size_t)m->cap, sizeof(MapNode *));
    if (!m->buckets) abort();
}

void map_destroy(Map *m) {
    for (int i = 0; i < m->cap; ++i) {
        MapNode *n = m->buckets[i];
        while (n) {
            MapNode *nx = n->next;
            free(n->key);
            free(n);
            n = nx;
        }
    }
    free(m->buckets);
    m->buckets = NULL;
    m->cap = m->count = 0;
}

static void map_grow(Map *m) {
    int ncap = m->cap * 2;
    MapNode **nb = (MapNode **)calloc((size_t)ncap, sizeof(MapNode *));
    if (!nb) abort();
    for (int i = 0; i < m->cap; ++i) {
        MapNode *n = m->buckets[i];
        while (n) {
            MapNode *nx = n->next;
            unsigned long long h = hash_str(n->key) & (unsigned long long)(ncap - 1);
            n->next = nb[h];
            nb[h] = n;
            n = nx;
        }
    }
    free(m->buckets);
    m->buckets = nb;
    m->cap = ncap;
}

void map_set(Map *m, const char *key, void *value) {
    unsigned long long h = hash_str(key) & (unsigned long long)(m->cap - 1);
    for (MapNode *n = m->buckets[h]; n; n = n->next) {
        if (strcmp(n->key, key) == 0) {
            n->value = value;
            return;
        }
    }
    if (m->count + 1 > m->cap * 3 / 4) map_grow(m);
    MapNode *n = (MapNode *)malloc(sizeof(MapNode));
    if (!n) abort();
    n->key = dup_str(key);
    if (!n->key) abort();
    n->value = value;
    h = hash_str(key) & (unsigned long long)(m->cap - 1);
    n->next = m->buckets[h];
    m->buckets[h] = n;
    m->count++;
}

void *map_get(Map *m, const char *key) {
    unsigned long long h = hash_str(key) & (unsigned long long)(m->cap - 1);
    for (MapNode *n = m->buckets[h]; n; n = n->next) {
        if (strcmp(n->key, key) == 0) return n->value;
    }
    return NULL;
}

/* ------------------------------- 环境 -------------------------------- */

Env *env_new(Env *parent, Arena *a) {
    (void)a;
    Env *e = (Env *)malloc(sizeof(Env));
    if (!e) abort();
    e->parent = parent;
    map_init(&e->vars);
    return e;
}

void env_free(Env *e) {
    if (!e) return;
    map_destroy(&e->vars);
    free(e);
}

Value *env_get(Env *e, const char *name) {
    for (Env *c = e; c; c = c->parent) {
        Value *v = (Value *)map_get(&c->vars, name);
        if (v) return v;
    }
    return NULL;
}

void env_define(Env *e, const char *name, Value v, Arena *a) {
    Value *slot = (Value *)arena_alloc(a, sizeof(Value));
    *slot = v;
    map_set(&e->vars, name, slot);
}

void env_assign(Env *e, const char *name, Value v, Arena *a) {
    (void)a;
    for (Env *c = e; c; c = c->parent) {
        Value *slot = (Value *)map_get(&c->vars, name);
        if (slot) {
            *slot = v;   /* 原地更新, 不重新分配 —— 使多闭包共享同一槽位的可变状态正确 */
            return;
        }
    }
    env_define(e, name, v, a); /* 全局新建 */
}

void env_link(Env *e, const char *name, Value *slot) {
    map_set(&e->vars, name, slot);
}

Env *env_get_owner(Env *e, const char *name, Value **out) {
    for (Env *c = e; c; c = c->parent) {
        Value *v = (Value *)map_get(&c->vars, name);
        if (v) { if (out) *out = v; return c; }
    }
    if (out) *out = NULL;
    return NULL;
}

Env *env_root(Env *e) {
    if (!e) return NULL;
    while (e->parent) e = e->parent;
    return e;
}