#ifndef DTOB_INTERNAL_H
#define DTOB_INTERNAL_H

#include "dtob.h"
#include "json.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/* ------------------------------------------------------------------ */
/*  Trit codec                                                        */
/* ------------------------------------------------------------------ */

/* Encode bytes to trit pairs (each byte → 6 trits as 00/01/10).
 * Output is padded to byte boundary with 11 pairs.
 * Returns total output BYTES (not trits). Caller frees. */
size_t trit_encode_padded(const uint8_t *bytes, size_t byte_len,
                          uint8_t **out_buf);

/* Decode trit-encoded, byte-padded buffer back to bytes.
 * Stops reading trit pairs when it hits a 11 pair (padding).
 * Returns number of decoded bytes. Caller frees. */
size_t trit_decode_padded(const uint8_t *buf, size_t buf_len,
                          uint8_t **out_bytes);

/* ------------------------------------------------------------------ */
/*  Lexer (byte-aligned)                                              */
/* ------------------------------------------------------------------ */

typedef enum {
    TOK_DATA,
    TOK_OPEN,         /* 0  */
    TOK_ARR_CLOSE,    /* 1  */
    TOK_KV_CLOSE,     /* 2  */
    TOK_TYPES_CLOSE,  /* 3  */
    TOK_UQT,          /* 4  */
    TOK_T_RAW,        /* 5  */
    TOK_T_FLOAT,      /* 6  */
    TOK_T_DOUBLE,     /* 7  */
    TOK_T_INT8,       /* 8  */
    TOK_T_INT16,      /* 9  */
    TOK_T_INT32,      /* 10 */
    TOK_T_INT64,      /* 11 */
    TOK_T_UINT8,      /* 12 */
    TOK_T_UINT16,     /* 13 */
    TOK_T_UINT32,     /* 14 */
    TOK_T_UINT64,     /* 15 */
    TOK_CUSTOM,       /* 16-8190 (includes convention codes) */
    TOK_ERROR,
    TOK_END
} TokenType;

typedef struct {
    TokenType  type;
    uint16_t   custom_code;   /* valid when type == TOK_CUSTOM */
    uint8_t   *data;          /* decoded bytes for TOK_DATA */
    size_t     data_len;
} Token;

typedef struct {
    const uint8_t *buf;
    size_t         len;
    size_t         pos;       /* byte position */
} Lexer;

void  lexer_init(Lexer *l, const uint8_t *buf, size_t len);
Token lexer_next(Lexer *l);

/* ------------------------------------------------------------------ */
/*  AST helpers                                                       */
/* ------------------------------------------------------------------ */

DtobValue *ast_make(DtobType type);
void       ast_add_element(DtobValue *arr, DtobValue *el);
void       ast_add_pair(DtobValue *kvs, uint8_t *key, size_t key_len,
                        DtobValue *val);

/* ------------------------------------------------------------------ */
/*  Pointer cache (for backref resolution) — hash table                */
/* ------------------------------------------------------------------ */

#define PTRCACHE_BUCKETS 256

typedef struct PtrCacheEntry PtrCacheEntry;
struct PtrCacheEntry {
    size_t         offset;
    DtobValue     *value;
    PtrCacheEntry *next;
};

typedef struct {
    PtrCacheEntry *buckets[PTRCACHE_BUCKETS];
} PtrCache;

void       ptrcache_init(PtrCache *cache);
DtobValue *ptrcache_lookup(PtrCache *cache, size_t offset);
void       ptrcache_add(PtrCache *cache, size_t offset, DtobValue *value);
void       ptrcache_free(PtrCache *cache);

/* ------------------------------------------------------------------ */
/*  Byte writer (for encoder)                                         */
/* ------------------------------------------------------------------ */

typedef struct {
    uint8_t *buf;
    size_t   cap;
    size_t   pos;
    int      error;
    int      strict_validation;
} ByteWriter;

void bw_init(ByteWriter *w, int strict_validation);
void bw_write_byte(ByteWriter *w, uint8_t b);
void bw_write_ctrl(ByteWriter *w, uint16_t code);
void bw_write_data(ByteWriter *w, const uint8_t *bytes, size_t len);

#endif
