/*
 * 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>

namespace URL {
namespace FFI {

enum class IgnoreCase : uint8_t {
    Yes,
    No,
};

enum class RustUrlPatternComponent : uint8_t {
    Protocol,
    Username,
    Password,
    Hostname,
    Port,
    Pathname,
    Search,
    Hash,
};

enum class RustUrlHostKind : uint8_t {
    String,
    Ipv4,
    Ipv6,
};

enum class State : uint8_t {
    SchemeStart,
    Scheme,
    NoScheme,
    SpecialRelativeOrAuthority,
    PathOrAuthority,
    Relative,
    RelativeSlash,
    SpecialAuthoritySlashes,
    SpecialAuthorityIgnoreSlashes,
    Authority,
    Host,
    Hostname,
    Port,
    File,
    FileSlash,
    FileHost,
    PathStart,
    Path,
    OpaquePath,
    Query,
    Fragment,
};

/// Opaque URLPattern handle.
struct RustUrlPattern;

struct RustUrlByteSlice {
    const uint8_t *data;
    size_t length;
};

struct RustUrlPatternInit {
    bool has_protocol;
    RustUrlByteSlice protocol;
    bool has_username;
    RustUrlByteSlice username;
    bool has_password;
    RustUrlByteSlice password;
    bool has_hostname;
    RustUrlByteSlice hostname;
    bool has_port;
    RustUrlByteSlice port;
    bool has_pathname;
    RustUrlByteSlice pathname;
    bool has_search;
    RustUrlByteSlice search;
    bool has_hash;
    RustUrlByteSlice hash;
    bool has_base_url;
    RustUrlByteSlice base_url;
};

struct RustUrlPatternResultInput {
    bool is_string;
    RustUrlByteSlice string;
    RustUrlPatternInit init;
};

struct RustUrlPatternGroup {
    RustUrlByteSlice name;
    bool has_value;
    RustUrlByteSlice value;
};

struct RustUrlPatternComponentResult {
    RustUrlByteSlice input;
    const RustUrlPatternGroup *groups;
    size_t group_count;
};

struct RustUrlPatternExecResult {
    const RustUrlPatternResultInput *inputs;
    size_t input_count;
    RustUrlPatternComponentResult protocol;
    RustUrlPatternComponentResult username;
    RustUrlPatternComponentResult password;
    RustUrlPatternComponentResult hostname;
    RustUrlPatternComponentResult port;
    RustUrlPatternComponentResult pathname;
    RustUrlPatternComponentResult search;
    RustUrlPatternComponentResult hash;
};

using FfiUrlPatternResultFn = void(*)(void*, const RustUrlPatternExecResult*);

struct FfiUrlHost {
    bool has_host;
    RustUrlHostKind kind;
    uint8_t ipv4[4];
    uint8_t ipv6[16];
    const uint8_t *string_data;
    size_t string_length;
};

struct RustFfiUrl {
    RustUrlByteSlice scheme;
    RustUrlByteSlice username;
    RustUrlByteSlice password;
    FfiUrlHost host;
    bool has_port;
    uint16_t port;
    const RustUrlByteSlice *path_segments;
    size_t path_segment_count;
    bool has_opaque_path;
    bool has_query;
    RustUrlByteSlice query;
    bool has_fragment;
    RustUrlByteSlice fragment;
};

/// FFI parse options borrowed from C++ storage.
///
/// The embedded `RustFfiUrl` values contain raw pointers into `UrlFfiStorage`
/// objects on the C++ side. Those storage objects must outlive the call to
/// `rust_url_basic_parse`.
struct RustBasicParseOptions {
    bool has_base_url;
    bool has_url;
    RustFfiUrl base_url;
    RustFfiUrl url;
    bool has_state_override;
    State state_override;
    RustUrlByteSlice encoding;
};

using FfiUrlResultFn = void(*)(void*, const RustFfiUrl*);

using FfiHostResultFn = void(*)(void*, const FfiUrlHost*);

extern "C" {

extern uint8_t *ladybird_rust_alloc(size_t size, size_t alignment);

extern uint8_t *ladybird_rust_alloc_zeroed(size_t size, size_t alignment);

extern void ladybird_rust_dealloc(uint8_t *ptr, size_t alignment);

extern uint8_t *ladybird_rust_realloc(uint8_t *ptr, size_t old_size, size_t new_size, size_t alignment);

/// Compile a URLPattern from a constructor string.
///
/// # Safety
/// `input` must be valid for `input_len` bytes of UTF-8. If `base_url` is non-null,
/// it must be valid for `base_url_len` bytes of UTF-8. `error_out` and
/// `error_len_out` must be valid pointers when non-null.
RustUrlPattern *rust_url_pattern_create_from_string(const uint8_t *input,
                                                    size_t input_len,
                                                    const uint8_t *base_url,
                                                    size_t base_url_len,
                                                    IgnoreCase ignore_case,
                                                    const uint8_t **error_out,
                                                    size_t *error_len_out);

/// Compile a URLPattern from an init dictionary.
///
/// # Safety
/// `init` must be a valid pointer. `error_out` and `error_len_out` must be
/// valid pointers when non-null.
RustUrlPattern *rust_url_pattern_create_from_init(const RustUrlPatternInit *init,
                                                  IgnoreCase ignore_case,
                                                  const uint8_t **error_out,
                                                  size_t *error_len_out);

/// Free an error string returned by a URLPattern create function.
///
/// # Safety
/// `error` must be a pointer returned via a create function's `error_out`, or null.
void rust_url_pattern_free_error(uint8_t *error, size_t len);

/// Free a compiled URLPattern.
///
/// # Safety
/// `pattern` must be a valid pointer returned by a create function, or null.
void rust_url_pattern_free(RustUrlPattern *pattern);

/// Return whether the pattern contains regexp groups.
///
/// # Safety
/// `pattern` must be a valid pointer returned by a create function.
bool rust_url_pattern_has_regexp_groups(const RustUrlPattern *pattern);

/// Return a component's canonical pattern string as a borrowed slice.
///
/// The returned slice is valid until `pattern` is freed.
///
/// # Safety
/// `pattern` must be a valid pointer returned by a create function.
RustUrlByteSlice rust_url_pattern_component_pattern_string(const RustUrlPattern *pattern,
                                                           RustUrlPatternComponent component);

/// Execute a compiled pattern against a string input and return a borrowed view
/// of the match result to a callback.
///
/// # Safety
/// `pattern` must be valid. `input` must be valid for `input_len` bytes of UTF-8.
/// If `base_url` is non-null, it must be valid for `base_url_len` bytes of UTF-8.
bool rust_url_pattern_exec_string(const RustUrlPattern *pattern,
                                  const uint8_t *input,
                                  size_t input_len,
                                  const uint8_t *base_url,
                                  size_t base_url_len,
                                  const uint8_t **error_out,
                                  size_t *error_len_out,
                                  void *ctx,
                                  FfiUrlPatternResultFn on_complete);

/// Execute a compiled pattern against an init dictionary and return a borrowed
/// view of the match result to a callback.
///
/// # Safety
/// `pattern` and `input` must be valid pointers.
bool rust_url_pattern_exec_init(const RustUrlPattern *pattern,
                                const RustUrlPatternInit *input,
                                const uint8_t **error_out,
                                size_t *error_len_out,
                                void *ctx,
                                FfiUrlPatternResultFn on_complete);

/// Test a compiled pattern against a string input.
///
/// # Safety
/// `pattern` must be valid. `input` must be valid for `input_len` bytes of UTF-8.
/// If `base_url` is non-null, it must be valid for `base_url_len` bytes of UTF-8.
bool rust_url_pattern_test_string(const RustUrlPattern *pattern,
                                  const uint8_t *input,
                                  size_t input_len,
                                  const uint8_t *base_url,
                                  size_t base_url_len);

/// Test a compiled pattern against an init dictionary.
///
/// # Safety
/// `pattern` and `input` must be valid pointers.
bool rust_url_pattern_test_init(const RustUrlPattern *pattern, const RustUrlPatternInit *input);

/// Test a compiled pattern against a parsed URL.
///
/// # Safety
/// `pattern` and `input` must be valid pointers.
bool rust_url_pattern_test_url(const RustUrlPattern *pattern, const RustFfiUrl *input);

/// # Safety
/// `input` must be valid for `input_length` bytes. `options` must be a valid pointer
/// whose embedded URL pointers remain valid for the duration of this call. `on_complete`
/// is called exactly once with the parse result.
bool rust_url_basic_parse(const uint8_t *input,
                          size_t input_length,
                          const RustBasicParseOptions *options,
                          void *ctx,
                          FfiUrlResultFn on_complete);

/// # Safety
/// `input` must be valid for `input_length` bytes.
/// `on_complete` is called exactly once with either a host result or null.
bool rust_url_parse_host(const uint8_t *input,
                         size_t input_length,
                         bool is_opaque,
                         void *ctx,
                         FfiHostResultFn on_complete);

}  // extern "C"

}  // namespace FFI
}  // namespace URL
