/*
 * Copyright (c) 2026-present, the Ladybird developers.
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

/* Generated with cbindgen:0.29.2 */

#include <stdint.h>
#include <stddef.h>

enum class RustFfiHtmlQuirksMode {
    No = 0,
    Limited = 1,
    Yes = 2,
};

enum class RustFfiHtmlNamespace {
    Html = 0,
    MathMl = 1,
    Svg = 2,
    Other = 3,
};

enum class RustFfiHtmlAttributeNamespace {
    None = 0,
    XLink = 1,
    Xml = 2,
    Xmlns = 3,
    Other = 4,
};

enum class RustFfiHtmlShadowRootMode {
    Open = 0,
    Closed = 1,
};

enum class RustFfiHtmlSlotAssignmentMode {
    Named = 0,
    Manual = 1,
};

enum class RustFfiHtmlParserRunResult {
    Ok = 0,
    Unsupported = 1,
    ExecuteScript = 2,
    ExecuteSvgScript = 3,
};

enum class RustFfiPreloadScannerAction {
    Base = 0,
    Fetch = 1,
};

enum class RustFfiPreloadScannerDestination {
    None = 0,
    Font = 1,
    Image = 2,
    Script = 3,
    Style = 4,
    Track = 5,
};

enum class RustFfiPreloadScannerCorsSetting {
    NoCors = 0,
    Anonymous = 1,
    UseCredentials = 2,
};

/// Opaque handle for the Rust HTML parser, passed across the FFI boundary.
struct RustFfiHtmlParserHandle;

/// Opaque handle for the Rust tokenizer, passed across the FFI boundary.
struct RustFfiTokenizerHandle;

/// C-compatible attribute representation.
struct RustFfiAttribute {
    /// If nonzero, an interned attribute-name id (1-based index into
    /// `interned_names::INTERNED_ATTR_NAMES`). When set, `name_ptr` /
    /// `name_len` are unused. Otherwise the pointer is UTF-16.
    uint16_t name_id;
    const uint16_t *name_ptr;
    size_t name_len;
    const uint8_t *value_ptr;
    size_t value_len;
    uint64_t name_start_line;
    uint64_t name_start_column;
    uint64_t name_end_line;
    uint64_t name_end_column;
    uint64_t value_start_line;
    uint64_t value_start_column;
    uint64_t value_end_line;
    uint64_t value_end_column;
};

/// C-compatible token representation.
///
/// Pointer fields borrow into buffers owned by the `RustFfiTokenizerHandle` that
/// produced this token. They remain valid only until the next call into the
/// tokenizer for that handle (any of `next_token`, `insert_input`, `destroy`,
/// etc.). Callers must consume the data before making the next call.
struct RustFfiToken {
    uint8_t token_type;
    uint32_t code_point;
    bool self_closing;
    bool had_duplicate_attribute;
    /// If nonzero, an interned tag-name id (1-based index into
    /// `interned_names::INTERNED_TAG_NAMES`). When set, `tag_name_ptr` /
    /// `tag_name_len` are unused and the C++ side uses its parallel
    /// Utf16FlyString table directly. Otherwise the pointer is UTF-16.
    uint16_t tag_name_id;
    const uint16_t *tag_name_ptr;
    size_t tag_name_len;
    const uint8_t *comment_ptr;
    size_t comment_len;
    const uint8_t *doctype_name_ptr;
    size_t doctype_name_len;
    const uint8_t *public_id_ptr;
    size_t public_id_len;
    const uint8_t *system_id_ptr;
    size_t system_id_len;
    bool force_quirks;
    bool missing_name;
    bool missing_public_id;
    bool missing_system_id;
    const RustFfiAttribute *attributes_ptr;
    size_t attributes_len;
    uint64_t start_line;
    uint64_t start_column;
    uint64_t end_line;
    uint64_t end_column;
};

struct RustFfiHtmlParserAttribute {
    const uint16_t *local_name_ptr;
    size_t local_name_len;
    const uint16_t *prefix_ptr;
    size_t prefix_len;
    RustFfiHtmlAttributeNamespace namespace_;
    const uint8_t *value_ptr;
    size_t value_len;
};

struct RustFfiHtmlParserContextAttribute {
    const uint16_t *local_name_ptr;
    size_t local_name_len;
    const uint16_t *prefix_ptr;
    size_t prefix_len;
    RustFfiHtmlAttributeNamespace namespace_;
    const uint8_t *value_ptr;
    size_t value_len;
};

struct RustFfiPreloadScannerEntry {
    RustFfiPreloadScannerAction action;
    const uint8_t *url_ptr;
    size_t url_len;
    RustFfiPreloadScannerDestination destination;
    RustFfiPreloadScannerCorsSetting cors_setting;
};

extern "C" {

/// Create a new Rust HTML tokenizer from UTF-32 code points.
///
/// # Safety
/// `input` must point to `len` valid u32 values.
RustFfiTokenizerHandle *rust_html_tokenizer_create(const uint32_t *input, size_t len);

/// Create a new Rust HTML tokenizer directly from a UTF-8 byte buffer.
/// Rust decodes the bytes to code points internally, skipping the C++
/// side's 4x-expanded Vec<u32> copy.
///
/// # Safety
/// `bytes` must point to `len` valid UTF-8 bytes.
RustFfiTokenizerHandle *rust_html_tokenizer_create_from_utf8(const uint8_t *bytes, size_t len);

/// Get the next token from the tokenizer.
/// Returns true if a token was produced, false if no more tokens.
///
/// # Safety
/// `handle` must be a valid pointer from `rust_html_tokenizer_create`.
/// `out` must be a valid pointer to an RustFfiToken.
bool rust_html_tokenizer_next_token(RustFfiTokenizerHandle *handle,
                                    RustFfiToken *out,
                                    bool stop_at_insertion_point,
                                    bool cdata_allowed);

/// Switch the tokenizer to a new state.
///
/// # Safety
/// `handle` must be a valid pointer from `rust_html_tokenizer_create`.
void rust_html_tokenizer_switch_state(RustFfiTokenizerHandle *handle, uint8_t state);

/// Insert input (as UTF-32 code points) at the current insertion point.
///
/// # Safety
/// `handle` must be a valid pointer. `input` must point to `len` valid u32 values.
void rust_html_tokenizer_insert_input(RustFfiTokenizerHandle *handle, const uint32_t *input, size_t len);

/// Append input (as UTF-32 code points) to the tokenizer input stream.
///
/// # Safety
/// `handle` must be a valid pointer. `input` must point to `len` valid u32 values.
void rust_html_tokenizer_append_input(RustFfiTokenizerHandle *handle, const uint32_t *input, size_t len);

/// Get the tokenizer input that has not been consumed yet.
///
/// # Safety
/// `handle`, `out_ptr`, and `out_len` must be valid pointers.
void rust_html_tokenizer_unparsed_input(RustFfiTokenizerHandle *handle, const uint8_t **out_ptr, size_t *out_len);

/// Compact already-tokenized input after the parser has consumed a chunk.
///
/// # Safety
/// `handle` must be a valid pointer.
void rust_html_tokenizer_parser_did_run(RustFfiTokenizerHandle *handle);

/// # Safety
/// `handle` must be a valid pointer.
void rust_html_tokenizer_store_insertion_point(RustFfiTokenizerHandle *handle);

/// # Safety
/// `handle` must be a valid pointer.
void rust_html_tokenizer_restore_insertion_point(RustFfiTokenizerHandle *handle);

/// # Safety
/// `handle` must be a valid pointer.
void rust_html_tokenizer_update_insertion_point(RustFfiTokenizerHandle *handle);

/// # Safety
/// `handle` must be a valid pointer.
void rust_html_tokenizer_undefine_insertion_point(RustFfiTokenizerHandle *handle);

/// # Safety
/// `handle` must be a valid pointer.
bool rust_html_tokenizer_is_insertion_point_defined(RustFfiTokenizerHandle *handle);

/// # Safety
/// `handle` must be a valid pointer.
bool rust_html_tokenizer_is_insertion_point_reached(RustFfiTokenizerHandle *handle);

/// # Safety
/// `handle` must be a valid pointer.
void rust_html_tokenizer_set_input_stream_closed(RustFfiTokenizerHandle *handle, bool closed);

/// # Safety
/// `handle` must be a valid pointer.
void rust_html_tokenizer_insert_eof(RustFfiTokenizerHandle *handle);

/// # Safety
/// `handle` must be a valid pointer.
void rust_html_tokenizer_abort(RustFfiTokenizerHandle *handle);

/// Destroy a Rust HTML tokenizer.
///
/// # Safety
/// `handle` must be a valid pointer from `rust_html_tokenizer_create`,
/// and must not be used after this call.
void rust_html_tokenizer_destroy(RustFfiTokenizerHandle *handle);

/// Number of interned HTML tag names known to the Rust tokenizer.
size_t rust_html_tokenizer_interned_tag_name_count();

/// Number of interned HTML attribute names known to the Rust tokenizer.
size_t rust_html_tokenizer_interned_attr_name_count();

/// Write the bytes and length of the interned tag name with the given
/// 1-based id to the caller-provided out parameters. On unknown ids the
/// out parameters are set to (null, 0).
///
/// # Safety
/// `out_ptr` and `out_len` must be valid pointers.
void rust_html_tokenizer_interned_tag_name(uint16_t id, const uint8_t **out_ptr, size_t *out_len);

/// Same as `rust_html_tokenizer_interned_tag_name` for attribute names.
///
/// # Safety
/// `out_ptr` and `out_len` must be valid pointers.
void rust_html_tokenizer_interned_attr_name(uint16_t id, const uint8_t **out_ptr, size_t *out_len);

extern size_t ladybird_html_parser_document_node(void *parser);

extern size_t ladybird_html_parser_document_html_element(void *parser);

extern void ladybird_html_parser_set_document_quirks_mode(void *parser, RustFfiHtmlQuirksMode mode);

extern void ladybird_html_parser_log_parse_error(void *parser, const uint8_t *message_ptr, size_t message_len);

extern void ladybird_html_parser_stop_parsing(void *parser);

extern bool ladybird_html_parser_parse_errors_enabled();

extern void ladybird_html_parser_visit_node(void *visitor, size_t node);

extern size_t ladybird_html_parser_create_document_type(void *parser,
                                                        const uint16_t *name_ptr,
                                                        size_t name_len,
                                                        const uint8_t *public_id_ptr,
                                                        size_t public_id_len,
                                                        const uint8_t *system_id_ptr,
                                                        size_t system_id_len);

extern size_t ladybird_html_parser_create_comment(void *parser, const uint8_t *data_ptr, size_t data_len);

extern void ladybird_html_parser_insert_text(size_t parent, size_t before, const uint8_t *data_ptr, size_t data_len);

extern void ladybird_html_parser_add_missing_attribute(size_t element,
                                                       const uint16_t *local_name_ptr,
                                                       size_t local_name_len,
                                                       const uint8_t *value_ptr,
                                                       size_t value_len);

extern void ladybird_html_parser_remove_node(size_t node);

extern void ladybird_html_parser_handle_element_popped(size_t element);

extern void ladybird_html_parser_prepare_svg_script(void *parser, size_t element, size_t source_line_number);

extern void ladybird_html_parser_set_script_source_line(void *parser, size_t element, size_t source_line_number);

extern void ladybird_html_parser_mark_script_already_started(void *parser, size_t element);

extern size_t ladybird_html_parser_parent_node(size_t node);

extern size_t ladybird_html_parser_create_element(void *parser,
                                                  size_t intended_parent,
                                                  RustFfiHtmlNamespace namespace_,
                                                  const uint16_t *namespace_uri_ptr,
                                                  size_t namespace_uri_len,
                                                  const uint16_t *local_name_ptr,
                                                  size_t local_name_len,
                                                  const RustFfiHtmlParserAttribute *attributes,
                                                  size_t attribute_count,
                                                  bool had_duplicate_attribute,
                                                  size_t form_element,
                                                  bool has_template_element_on_stack);

extern void ladybird_html_parser_append_child(size_t parent, size_t child);

extern void ladybird_html_parser_insert_node(size_t parent,
                                             size_t before,
                                             size_t child,
                                             bool queue_custom_element_reactions);

extern void ladybird_html_parser_move_all_children(size_t from, size_t to);

extern size_t ladybird_html_parser_template_content(size_t element);

extern size_t ladybird_html_parser_attach_declarative_shadow_root(size_t host,
                                                                  RustFfiHtmlShadowRootMode mode,
                                                                  RustFfiHtmlSlotAssignmentMode slot_assignment,
                                                                  bool clonable,
                                                                  bool serializable,
                                                                  bool delegates_focus,
                                                                  bool keep_custom_element_registry_null);

extern void ladybird_html_parser_set_template_content(size_t element, size_t content);

extern bool ladybird_html_parser_allows_declarative_shadow_roots(size_t node);

/// Create a new Rust HTML parser.
RustFfiHtmlParserHandle *rust_html_parser_create();

/// Initialize the Rust HTML parser for the HTML fragment parsing algorithm.
///
/// # Safety
/// `handle` must be a valid pointer from `rust_html_parser_create`.
/// `context_local_name_ptr` must point to `context_local_name_len` valid UTF-16 code units.
void rust_html_parser_begin_fragment(RustFfiHtmlParserHandle *handle,
                                     size_t root,
                                     size_t context_element,
                                     RustFfiHtmlNamespace context_namespace,
                                     const uint16_t *context_namespace_uri_ptr,
                                     size_t context_namespace_uri_len,
                                     const uint16_t *context_local_name_ptr,
                                     size_t context_local_name_len,
                                     const RustFfiHtmlParserContextAttribute *context_attributes,
                                     size_t context_attribute_count,
                                     RustFfiHtmlQuirksMode document_quirks_mode,
                                     size_t form_element);

/// Run the Rust HTML parser.
///
/// Returns `ExecuteScript` when tree construction reaches a parser-blocking script
/// and the C++ host needs to run the script before tokenization can continue.
///
/// # Safety
/// `handle` must be a valid pointer from `rust_html_parser_create`.
RustFfiHtmlParserRunResult rust_html_parser_run_document(RustFfiHtmlParserHandle *handle,
                                                         RustFfiTokenizerHandle *tokenizer,
                                                         void *host,
                                                         bool scripting_enabled,
                                                         bool stop_at_insertion_point);

/// Pop all open elements at the end of parsing.
///
/// # Safety
/// `handle` must be a valid pointer from `rust_html_parser_create`.
void rust_html_parser_pop_all_open_elements(RustFfiHtmlParserHandle *handle);

/// Visit all DOM nodes that are kept alive by the Rust HTML parser state.
///
/// # Safety
/// `handle` must be a valid pointer from `rust_html_parser_create`.
/// `visitor` must be a valid `GC::Cell::Visitor`.
void rust_html_parser_visit_edges(const RustFfiHtmlParserHandle *handle, void *visitor);

/// Take the script element that caused the last Rust HTML parser run to stop.
///
/// # Safety
/// `handle` must be a valid pointer from `rust_html_parser_create`.
size_t rust_html_parser_take_pending_script(RustFfiHtmlParserHandle *handle);

/// Take the SVG script element that caused the last Rust HTML parser run to stop.
///
/// # Safety
/// `handle` must be a valid pointer from `rust_html_parser_create`.
size_t rust_html_parser_take_pending_svg_script(RustFfiHtmlParserHandle *handle);

/// Return how many times this parser handle has been asked to run.
///
/// # Safety
/// `handle` must be a valid pointer from `rust_html_parser_create`.
uint64_t rust_html_parser_run_count(const RustFfiHtmlParserHandle *handle);

/// Destroy a Rust HTML parser.
///
/// # Safety
/// `handle` must be a valid pointer from `rust_html_parser_create`,
/// and must not be used after this call.
void rust_html_parser_destroy(RustFfiHtmlParserHandle *handle);

/// Scan pending parser input for resources the speculative HTML parser can fetch.
///
/// # Safety
/// `input` must point to `input_len` valid UTF-8 bytes. `callback` must not retain pointers
/// from the provided entry beyond the callback invocation.
void rust_html_preload_scanner_scan(const uint8_t *input,
                                    size_t input_len,
                                    void *ctx,
                                    bool (*callback)(void *ctx, const RustFfiPreloadScannerEntry *entry));

}  // extern "C"
