struct PDFPage {
    String string;
    int    number;
};

struct PDF {
    String         filename;
    Array<PDFPage> pages;
};

// @todo: pull request the object close
// @todo: something needs to be done with unicode codepoints
PDF pdfioReadPDF(Allocator allocator, String filename) {
    Assert(filename.data[filename.len] == 0);
    PDF result      = {};
    result.pages    = {allocator};
    result.filename = filename;

    pdfio_file_t *file = pdfioFileOpen(filename.data, NULL, NULL, NULL, NULL);
    Assert(file);
    defer { pdfioFileClose(file); };

    char   buffer[1024];
    size_t page_count = pdfioFileGetNumPages(file);
    result.pages.reserve(page_count);

    for (size_t page_i = 0; page_i < page_count; page_i += 1) {
        pdfio_obj_t *obj = pdfioFileGetPage(file, page_i);
        if (obj == NULL) continue;
        defer { pdfioObjClose(obj); };
        PDFPage *page = result.pages.alloc();
        page->number  = (int)page_i;

        Scratch       scratch((Arena *)allocator.object);
        Array<String> strings     = {scratch};
        size_t        num_streams = pdfioPageGetNumStreams(obj);
        for (size_t stream_i = 0; stream_i < num_streams; stream_i += 1) {
            pdfio_stream_t *st = pdfioPageOpenStream(obj, stream_i, true);
            if (st == NULL) continue;
            defer { pdfioStreamClose(st); };

            bool first = true;
            while (pdfioStreamGetToken(st, buffer, sizeof(buffer))) {
                if (buffer[0] == '(') {
                    if (first) {
                        first = false;
                    }

                    strings.add(Copy(scratch, buffer + 1));
                } else if (!strcmp(buffer, "Td") || !strcmp(buffer, "TD") || !strcmp(buffer, "T*") || !strcmp(buffer, "\'") || !strcmp(buffer, "\"")) {
                    first = true;
                }
            }
        }
        page->string = Merge(allocator, strings, "");
    }

    return result;
}

#if 1
extern "C" void OutputDebugStringA(const char *);
void            Printf(const char *string, ...) {
    Scratch scratch;
    STRING_FORMAT(scratch, string, result);
    OutputDebugStringA(result.data);
}
#else
    #define Printf(...) (0)
#endif

void PrintPDF(PDF pdf) {
    For(pdf.pages) {
        Printf("%d, %.*s\n", it.number, FmtString(it.string));
    }
}