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

static void ensure_cap(Document *doc, int needed) {
    if (needed <= doc->cap) return;
    int newCap = doc->cap > 0 ? doc->cap : 8;
    while (newCap < needed) newCap *= 2;
    doc->blocks = realloc(doc->blocks, (size_t)newCap * sizeof(Block));
    doc->cap = newCap;
}

void document_init(Document *doc) {
    doc->blocks = NULL;
    doc->count = 0;
    doc->cap = 0;
    document_insert_block(doc, 0, BLOCK_PARAGRAPH, "", 0);
}

void document_free(Document *doc) {
    for (int i = 0; i < doc->count; i++) {
        sb_free(&doc->blocks[i].text);
        sb_free(&doc->blocks[i].lang);
        sb_free(&doc->blocks[i].alt);
    }
    free(doc->blocks);
    doc->blocks = NULL;
    doc->count = 0;
    doc->cap = 0;
}

void document_insert_block(Document *doc, int index, BlockType type, const char *text, int len) {
    ensure_cap(doc, doc->count + 1);
    memmove(&doc->blocks[index + 1], &doc->blocks[index], (size_t)(doc->count - index) * sizeof(Block));
    doc->count++;
    Block *b = &doc->blocks[index];
    b->type = type;
    sb_init(&b->text);
    sb_append(&b->text, text, len);
    sb_init(&b->lang);
    sb_init(&b->alt);
    b->tableCol = 0;
    b->tableCols = 0;
    b->tableAlign = 0;
}

void document_clone(Document *dst, const Document *src) {
    dst->count = src->count;
    dst->cap = src->count;
    dst->blocks = dst->cap > 0 ? malloc((size_t)dst->cap * sizeof(Block)) : NULL;
    for (int i = 0; i < src->count; i++) {
        dst->blocks[i].type = src->blocks[i].type;
        sb_init(&dst->blocks[i].text);
        sb_append(&dst->blocks[i].text, src->blocks[i].text.data, src->blocks[i].text.len);
        sb_init(&dst->blocks[i].lang);
        sb_append(&dst->blocks[i].lang, src->blocks[i].lang.data, src->blocks[i].lang.len);
        sb_init(&dst->blocks[i].alt);
        sb_append(&dst->blocks[i].alt, src->blocks[i].alt.data, src->blocks[i].alt.len);
        dst->blocks[i].tableCol = src->blocks[i].tableCol;
        dst->blocks[i].tableCols = src->blocks[i].tableCols;
        dst->blocks[i].tableAlign = src->blocks[i].tableAlign;
    }
}

void document_remove_block(Document *doc, int index) {
    sb_free(&doc->blocks[index].text);
    sb_free(&doc->blocks[index].lang);
    sb_free(&doc->blocks[index].alt);
    memmove(&doc->blocks[index], &doc->blocks[index + 1], (size_t)(doc->count - index - 1) * sizeof(Block));
    doc->count--;
}
