/* rust-pdf C ABI — generated by cbindgen. Do not edit by hand. */

#ifndef RUST_PDF_H
#define RUST_PDF_H

/* This file is auto-generated. Run `make header` to regenerate. */

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

/**
 * Status code returned by every fallible export.
 */
typedef enum {
    PDF_STATUS_OK = 0,
    PDF_STATUS_NULL_POINTER = 1,
    PDF_STATUS_INVALID_UTF8 = 2,
    PDF_STATUS_IO = 3,
    PDF_STATUS_SERIALIZE = 4,
    PDF_STATUS_PANIC = 5,
    /**
     * A document/argument could not be parsed.
     */
    PDF_STATUS_PARSE = 6,
    /**
     * A font could not be loaded/embedded.
     */
    PDF_STATUS_FONT = 7,
    /**
     * An image could not be decoded/embedded.
     */
    PDF_STATUS_IMAGE = 8,
    /**
     * Encryption setup failed.
     */
    PDF_STATUS_ENCRYPT = 9,
    /**
     * Digital signing failed.
     */
    PDF_STATUS_SIGN = 10,
    /**
     * An out-of-range index or other invalid argument.
     */
    PDF_STATUS_INVALID_ARGUMENT = 11,
    /**
     * License activation failed (bad signature, expired, or malformed).
     */
    PDF_STATUS_LICENSE = 12,
} PdfStatus;

/**
 * Opaque document handle. The C side only ever sees `*mut PdfDocument`.
 */
typedef struct PdfDocument PdfDocument;

/**
 * Opaque editable-document handle.
 */
typedef struct PdfEditable PdfEditable;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

/**
 * Library version as a static, NUL-terminated C string. Never freed by the
 * caller.
 *
 * # Safety
 * The returned pointer is valid for the lifetime of the program.
 */
const char *pdf_version(void);

/**
 * Return the last error message for the current thread, or NULL if none.
 * The pointer is owned by the library and valid until the next FFI call on
 * this thread.
 *
 * # Safety
 * Do not free the returned pointer or use it across other FFI calls.
 */
const char *pdf_last_error_message(void);

/**
 * Activate a license token for this process, unlocking the corporate features
 * it grants (PDF/A, signatures, encryption, accessibility) until it expires.
 * Returns [`PdfStatus::License`] if the token is forged, expired or malformed.
 *
 * # Safety
 * `token` must be a valid NUL-terminated UTF-8 C string.
 */
int pdf_activate_license(const char *token);

/**
 * Create a new, empty A4 document. Returns NULL on allocation failure.
 *
 * # Safety
 * The returned handle must eventually be passed to [`pdf_document_free`].
 */
PdfDocument *pdf_document_new(void);

/**
 * Free a document handle. Passing NULL is a no-op.
 *
 * # Safety
 * `doc` must have come from [`pdf_document_new`] and not be used afterwards.
 */
void pdf_document_free(PdfDocument *doc);

/**
 * Append a page using the document's default size (A4).
 *
 * # Safety
 * `doc` must be a valid handle from [`pdf_document_new`].
 */
int pdf_document_add_page(PdfDocument *doc);

/**
 * Set the fill color (DeviceRGB, components in 0..=1) on the current page.
 *
 * # Safety
 * `doc` must be valid and have at least one page.
 */
int pdf_page_set_fill_rgb(PdfDocument *doc, double r, double g, double b);

/**
 * Set the stroke color (DeviceRGB) on the current page.
 *
 * # Safety
 * `doc` must be valid and have at least one page.
 */
int pdf_page_set_stroke_rgb(PdfDocument *doc, double r, double g, double b);

/**
 * Set the line width on the current page.
 *
 * # Safety
 * `doc` must be valid and have at least one page.
 */
int pdf_page_set_line_width(PdfDocument *doc, double width);

/**
 * Append a rectangle subpath on the current page.
 *
 * # Safety
 * `doc` must be valid and have at least one page.
 */
int pdf_page_rect(PdfDocument *doc, double x, double y, double width, double height);

/**
 * Fill the current path (nonzero winding) on the current page.
 *
 * # Safety
 * `doc` must be valid and have at least one page.
 */
int pdf_page_fill(PdfDocument *doc);

/**
 * Stroke the current path on the current page.
 *
 * # Safety
 * `doc` must be valid and have at least one page.
 */
int pdf_page_stroke(PdfDocument *doc);

/**
 * Serialize the document and write it to `path` (a UTF-8, NUL-terminated C
 * string).
 *
 * # Safety
 * `doc` must be valid; `path` must be a valid NUL-terminated C string.
 */
int pdf_document_save(PdfDocument *doc, const char *path);

/**
 * Serialize the document into a freshly-allocated buffer. On success writes
 * the pointer to `*out_ptr` and length to `*out_len`; the caller must release
 * it with [`pdf_buffer_free`].
 *
 * # Safety
 * `doc`, `out_ptr` and `out_len` must be valid, non-aliasing pointers.
 */
int pdf_document_write(PdfDocument *doc, unsigned char **out_ptr, uintptr_t *out_len);

/**
 * Free a buffer returned by [`pdf_document_write`]. NULL is a no-op.
 *
 * # Safety
 * `ptr`/`len` must be exactly the pair produced by [`pdf_document_write`].
 */
void pdf_buffer_free(unsigned char *ptr, uintptr_t len);

/**
 * Number of pages in the document, or -1 on a null handle.
 *
 * # Safety
 * `doc` must be a valid handle or NULL.
 */
int pdf_document_page_count(const PdfDocument *doc);

/**
 * Mark the document as **PDF/A-2b**.
 *
 * # Safety
 * `doc` must be a valid handle.
 */
int pdf_document_pdfa(PdfDocument *doc);

/**
 * Mark the document as PDF/A at `level`: 0=A-1b, 1=A-2b, 2=A-2a, 3=A-3b,
 * 4=A-3a. Level-A variants also enable tagging.
 *
 * # Safety
 * `doc` must be a valid handle.
 */
int pdf_document_pdfa_level(PdfDocument *doc, int level);

/**
 * Enable the tagged structure tree (accessibility).
 *
 * # Safety
 * `doc` must be a valid handle.
 */
int pdf_document_tagged(PdfDocument *doc);

/**
 * Set the PDF version: 0=1.4, 1=1.5, 2=1.7.
 *
 * # Safety
 * `doc` must be a valid handle.
 */
int pdf_document_set_version(PdfDocument *doc, int v);

/**
 * Set the default page size (points) for subsequently added pages.
 *
 * # Safety
 * `doc` must be a valid handle.
 */
int pdf_document_set_default_size(PdfDocument *doc, double width, double height);

/**
 * Set document info. Any argument may be NULL to leave it unset.
 *
 * # Safety
 * `doc` must be valid; each string must be NULL or a valid C string.
 */
int pdf_document_set_info(PdfDocument *doc,
                                const char *title,
                                const char *author,
                                const char *subject,
                                const char *keywords,
                                const char *creator);

/**
 * Append a page with an explicit size (points).
 *
 * # Safety
 * `doc` must be a valid handle.
 */
int pdf_document_add_page_sized(PdfDocument *doc, double width, double height);

/**
 * Register a font from a file path; writes its id to `out_id`.
 *
 * # Safety
 * `doc`, `path` and `out_id` must be valid.
 */
int pdf_document_add_font_file(PdfDocument *doc, const char *path, int *out_id);

/**
 * Register a font from raw TrueType/OpenType bytes; writes its id to `out_id`.
 *
 * # Safety
 * `doc`, `data` and `out_id` must be valid.
 */
int pdf_document_add_font(PdfDocument *doc, const uint8_t *data, uintptr_t len, int *out_id);

/**
 * Show a line of text at `(x, y)` (baseline) in `font`/`size` on the current
 * page. `heading_level` 1..=6 tags it as `H1`..`H6` (when the document is
 * tagged); 0 leaves it as a paragraph.
 *
 * # Safety
 * `doc` must be valid with at least one page; `text` a valid C string.
 */
int pdf_page_show_text(PdfDocument *doc,
                             int font,
                             double size,
                             double x,
                             double y,
                             const char *text,
                             int heading_level);

/**
 * Lay out a wrapping paragraph in the box `(x, y, width)` (y = first baseline)
 * with `align` (0=left,1=right,2=center,3=justify) on the current page.
 *
 * # Safety
 * `doc` must be valid with at least one page; `text` a valid C string.
 */
int pdf_page_paragraph(PdfDocument *doc,
                             int font,
                             double size,
                             double x,
                             double y,
                             double width,
                             int align,
                             const char *text);

/**
 * Register an image from a file (JPEG or PNG by signature); id → `out_id`.
 *
 * # Safety
 * `doc`, `path`, `out_id` must be valid.
 */
int pdf_document_add_image_file(PdfDocument *doc, const char *path, int *out_id);

/**
 * Register a PNG from bytes; id → `out_id`.
 *
 * # Safety
 * `doc`, `data`, `out_id` must be valid.
 */
int pdf_document_add_image_png(PdfDocument *doc,
                                     const uint8_t *data,
                                     uintptr_t len,
                                     int *out_id);

/**
 * Register a JPEG from bytes; id → `out_id`.
 *
 * # Safety
 * `doc`, `data`, `out_id` must be valid.
 */
int pdf_document_add_image_jpeg(PdfDocument *doc,
                                      const uint8_t *data,
                                      uintptr_t len,
                                      int *out_id);

/**
 * Draw a (decorative) image in `(x, y, w, h)` on the current page.
 *
 * # Safety
 * `doc` must be valid with at least one page.
 */
int pdf_page_draw_image(PdfDocument *doc, int image, double x, double y, double w, double h);

/**
 * Draw a meaningful image (tagged `/Figure` with alternate text `alt`).
 *
 * # Safety
 * `doc` must be valid with at least one page; `alt` a valid C string.
 */
int pdf_page_figure(PdfDocument *doc,
                          int image,
                          double x,
                          double y,
                          double w,
                          double h,
                          const char *alt);

/**
 * Attach an embedded file (PDF/A-3). `relationship`: 0=Source, 1=Data,
 * 2=Alternative, 3=Supplement, 4=Unspecified.
 *
 * # Safety
 * `doc`, `name`, `mime`, `data`, `desc` must be valid.
 */
int pdf_document_attach_file(PdfDocument *doc,
                                   const char *name,
                                   const char *mime,
                                   const uint8_t *data,
                                   uintptr_t len,
                                   int relationship,
                                   const char *desc);

/**
 * Add a text field (`rect` = x0,y0,x1,y1). `size` 0 = auto.
 *
 * # Safety
 * `doc`, `name`, `value` must be valid.
 */
int pdf_document_text_field(PdfDocument *doc,
                                  const char *name,
                                  uintptr_t page,
                                  double x0,
                                  double y0,
                                  double x1,
                                  double y1,
                                  const char *value,
                                  double size);

/**
 * Add a checkbox (`checked` != 0 = on).
 *
 * # Safety
 * `doc`, `name` must be valid.
 */
int pdf_document_checkbox(PdfDocument *doc,
                                const char *name,
                                uintptr_t page,
                                double x0,
                                double y0,
                                double x1,
                                double y1,
                                int checked);

/**
 * Add a dropdown (choice) field. `options` is a single string with entries
 * separated by `\n`; `selected` is the 0-based index or -1 for none.
 *
 * # Safety
 * `doc`, `name`, `options` must be valid.
 */
int pdf_document_dropdown(PdfDocument *doc,
                                const char *name,
                                uintptr_t page,
                                double x0,
                                double y0,
                                double x1,
                                double y1,
                                const char *options,
                                int selected,
                                double size);

/**
 * Add a radio-button group. `rects` holds `count*4` doubles (x0,y0,x1,y1 per
 * button); `exports` holds `count` C strings (the export value of each button);
 * `selected` is the 0-based index or -1.
 *
 * # Safety
 * `doc`, `name`, `rects` (count*4 doubles) and `exports` (count strings) valid.
 */
int pdf_document_radio_group(PdfDocument *doc,
                                   const char *name,
                                   uintptr_t page,
                                   uintptr_t count,
                                   const double *rects,
                                   const char *const *exports,
                                   int selected);

/**
 * Load and parse an existing PDF from bytes. Returns NULL on failure (see
 * [`pdf_last_error_message`](crate::pdf_last_error_message)).
 *
 * # Safety
 * `data`/`len` must describe a readable region.
 */
PdfEditable *pdf_editable_load(const uint8_t *data, uintptr_t len);

/**
 * Load an encrypted PDF using `password` (a NUL-terminated C string).
 *
 * # Safety
 * `data`/`len` readable; `password` a valid C string.
 */
PdfEditable *pdf_editable_load_password(const uint8_t *data, uintptr_t len, const char *password);

/**
 * Free an editable handle. NULL is a no-op.
 *
 * # Safety
 * `ed` must come from a `pdf_editable_load*` call and not be reused.
 */
void pdf_editable_free(PdfEditable *ed);

/**
 * Number of pages, or -1 on a null handle.
 *
 * # Safety
 * `ed` must be a valid handle or NULL.
 */
int pdf_editable_page_count(const PdfEditable *ed);

/**
 * Append all pages of `other` to `ed`.
 *
 * # Safety
 * Both handles must be valid.
 */
int pdf_editable_merge(PdfEditable *ed, const PdfEditable *other);

/**
 * Rotate page `index` by `degrees` (a multiple of 90).
 *
 * # Safety
 * `ed` must be valid.
 */
int pdf_editable_rotate_page(PdfEditable *ed, uintptr_t index, int degrees);

/**
 * Delete page `index`.
 *
 * # Safety
 * `ed` must be valid.
 */
int pdf_editable_delete_page(PdfEditable *ed, uintptr_t index);

/**
 * Reorder pages to the 0-based `order` (an array of `count` indices).
 *
 * # Safety
 * `ed` valid; `order` points to `count` `usize` values.
 */
int pdf_editable_reorder_pages(PdfEditable *ed, const uintptr_t *order, uintptr_t count);

/**
 * Extract pages `indices` (array of `count`) into a **new** editable handle,
 * returned via `out`. Returns NULL `*out` on failure.
 *
 * # Safety
 * `ed` valid; `indices` points to `count` `usize`; `out` writable.
 */
int pdf_editable_extract_pages(const PdfEditable *ed,
                                     const uintptr_t *indices,
                                     uintptr_t count,
                                     PdfEditable **out);

/**
 * Set an `/Info` entry (`key` → `value`).
 *
 * # Safety
 * `ed`, `key`, `value` must be valid.
 */
int pdf_editable_set_info(PdfEditable *ed, const char *key, const char *value);

/**
 * Read an `/Info` entry into a buffer (`out_ptr`/`out_len`); empty if absent.
 *
 * # Safety
 * `ed`, `key`, `out_ptr`, `out_len` must be valid.
 */
int pdf_editable_get_info(const PdfEditable *ed,
                                const char *key,
                                unsigned char **out_ptr,
                                uintptr_t *out_len);

/**
 * Replace the XMP `/Metadata` stream with `xml`.
 *
 * # Safety
 * `ed` valid; `xml`/`len` readable.
 */
int pdf_editable_set_xmp(PdfEditable *ed, const uint8_t *xml, uintptr_t len);

/**
 * Overlay raw content-stream bytes on page `index` (e.g. a watermark).
 *
 * # Safety
 * `ed` valid; `content`/`len` readable.
 */
int pdf_editable_overlay_page(PdfEditable *ed,
                                    uintptr_t index,
                                    const uint8_t *content,
                                    uintptr_t len);

/**
 * Fill an AcroForm text field by name. `out_found` (if non-NULL) gets 1 if the
 * field existed, else 0.
 *
 * # Safety
 * `ed`, `name`, `value` valid; `out_found` NULL or writable.
 */
int pdf_editable_fill_text_field(PdfEditable *ed,
                                       const char *name,
                                       const char *value,
                                       int *out_found);

/**
 * Drop unreferenced objects, recompress, dedupe and emit object streams on save.
 *
 * # Safety
 * `ed` must be valid.
 */
int pdf_editable_optimize(PdfEditable *ed);

/**
 * Toggle object streams + cross-reference stream output on save.
 *
 * # Safety
 * `ed` must be valid.
 */
int pdf_editable_compact(PdfEditable *ed, int on);

/**
 * Encrypt on save. `method`: 0=RC4-128, 1=AES-128, 2=AES-256/R6.
 * `read_only` != 0 applies the read-only permission set.
 *
 * # Safety
 * `ed`, `user`, `owner` valid.
 */
int pdf_editable_encrypt(PdfEditable *ed,
                               int method,
                               const char *user,
                               const char *owner,
                               int read_only);

/**
 * Serialize to a buffer (`out_ptr`/`out_len`), freed by `pdf_buffer_free`.
 *
 * # Safety
 * `ed`, `out_ptr`, `out_len` valid.
 */
int pdf_editable_to_bytes(const PdfEditable *ed, unsigned char **out_ptr, uintptr_t *out_len);

/**
 * Serialize as an incremental update over `original` (preserves it verbatim).
 *
 * # Safety
 * `ed`, `original`, `out_ptr`, `out_len` valid.
 */
int pdf_editable_to_bytes_incremental(const PdfEditable *ed,
                                            const uint8_t *original,
                                            uintptr_t original_len,
                                            unsigned char **out_ptr,
                                            uintptr_t *out_len);

/**
 * Save to `path`.
 *
 * # Safety
 * `ed`, `path` valid.
 */
int pdf_editable_save(const PdfEditable *ed, const char *path);

/**
 * Extract the document's text into a UTF-8 buffer (`out_ptr`/`out_len`).
 *
 * # Safety
 * `data`/`len` readable; `out_ptr`/`out_len` writable.
 */
int pdf_extract_text(const uint8_t *data,
                           uintptr_t len,
                           unsigned char **out_ptr,
                           uintptr_t *out_len);

/**
 * Sign `pdf` with a PKCS#8 DER private key + DER certificate, producing a new
 * PDF (incremental update) in `out_ptr`/`out_len`. `reason`/`location`/`name`
 * may be NULL; `pades` != 0 selects PAdES-B-B.
 *
 * # Safety
 * All `(ptr, len)` pairs readable; string args NULL or valid C strings;
 * `out_ptr`/`out_len` writable.
 */
int pdf_sign(const uint8_t *pdf,
                   uintptr_t pdf_len,
                   const uint8_t *key_der,
                   uintptr_t key_len,
                   const uint8_t *cert_der,
                   uintptr_t cert_len,
                   const char *reason,
                   const char *location,
                   const char *name,
                   int pades,
                   unsigned char **out_ptr,
                   uintptr_t *out_len);

/**
 * Append a document timestamp (`/DocTimeStamp`, PAdES-B-LTA) using a TSA key +
 * cert. `date` may be NULL (a fixed reproducible value is used).
 *
 * # Safety
 * All `(ptr, len)` pairs readable; `out_ptr`/`out_len` writable.
 */
int pdf_timestamp(const uint8_t *pdf,
                        uintptr_t pdf_len,
                        const uint8_t *key_der,
                        uintptr_t key_len,
                        const uint8_t *cert_der,
                        uintptr_t cert_len,
                        const char *date,
                        unsigned char **out_ptr,
                        uintptr_t *out_len);

/**
 * Append a Document Security Store (`/DSS`, PAdES-B-LT) with the given DER
 * certificates and CRLs. Each is passed as parallel `ptr`/`len` arrays.
 *
 * # Safety
 * `cert_ptrs`/`cert_lens` have `cert_count` entries; `crl_ptrs`/`crl_lens`
 * have `crl_count`; every entry readable; `out_ptr`/`out_len` writable.
 */
int pdf_add_dss(const uint8_t *pdf,
                      uintptr_t pdf_len,
                      const uint8_t *const *cert_ptrs,
                      const uintptr_t *cert_lens,
                      uintptr_t cert_count,
                      const uint8_t *const *crl_ptrs,
                      const uintptr_t *crl_lens,
                      uintptr_t crl_count,
                      unsigned char **out_ptr,
                      uintptr_t *out_len);

#ifdef __cplusplus
}  // extern "C"
#endif  // __cplusplus

#endif  /* RUST_PDF_H */
