/**
 * Public types exported by ua-word-stress.
 */
/**
 * Full morphological reading for one stress variant of an ambiguous word form.
 *
 * Populated only when the variants file (`ua_stress.variants.json.gz`) is loaded
 * via `UaStressTrie.loadVariants()`.
 */
interface StressVariant {
    /** 0-based stressed vowel index (among Ukrainian vowels in the word). */
    stress: number;
    /**
     * Universal POS tag (UPOS), e.g. `"NOUN"`, `"VERB"`.
     * `null` if not stored for this entry.
     */
    pos: string | null;
    /**
     * Universal Dependencies morphological features, e.g.
     * `{ Case: "Nom", Number: "Plur", Gender: "Masc" }`.
     * Empty object when no features are available.
     */
    feats: Record<string, string>;
    /**
     * Base form (lemma) of the word, e.g. `"замок"`.
     * `null` if not stored.
     */
    lemma: string | null;
    /**
     * Short Wiktionary gloss that disambiguates the meaning, e.g. `"castle"` vs `"lock"`.
     * `null` when not available.
     */
    definition: string | null;
}
/** Result of a full stress lookup. */
interface LookupResult {
    /**
     * All stressed vowel indices (0-based among Ukrainian vowels in the word),
     * in order from most common to least common.
     *
     * - Length 1 → unambiguous stress.
     * - Length 2 → two valid positions; see `type` for interpretation.
     *
     * @example
     * // 'університет': vowels у(0) і(1) е(2) и(3) е(4) → stresses=[4]
     * // 'замок':       vowels а(0) о(1)               → stresses=[0, 1]
     * // 'помилка':     vowels о(0) и(1) а(2)           → stresses=[0, 1]
     */
    stresses: number[];
    /**
     * Convenience alias for `stresses[0]` — the primary (most common) stress.
     */
    stress: number;
    /**
     * Stress classification:
     *
     * - `"unique"`    — one unambiguous stress position.
     * - `"variative"` — multiple positions, all orthographically valid
     *                   simultaneously (e.g. _по́милка_ / _поми́лка_).
     *                   Any position is correct; present both or pick either.
     * - `"heteronym"` — multiple positions corresponding to different
     *                   meanings or grammatical forms
     *                   (e.g. _за́мок_ "castle" / _замо́к_ "lock";
     *                    _бло́хи_ gen.sg / _блохи́_ nom.pl).
     *                   The correct stress depends on the intended meaning/form;
     *                   context-aware disambiguation is required.
     */
    type: "unique" | "variative" | "heteronym";
    /**
     * Full per-variant morphological data.
     *
     * Populated only when `UaStressTrie.loadVariants()` has been called and this
     * word has multiple stress positions.  `null` otherwise.
     *
     * @example
     * // замок → variants loaded:
     * // [
     * //   { stress: 0, pos: "NOUN", feats: { Case: "Nom", Number: "Sing" }, lemma: "замок", definition: "castle" },
     * //   { stress: 1, pos: "NOUN", feats: { Case: "Nom", Number: "Sing" }, lemma: "замок", definition: "lock" },
     * // ]
     */
    variants: StressVariant[] | null;
    /**
     * @deprecated Use `type !== "unique"` instead.
     * Kept for backward compatibility with v1 consumers.
     */
    uncertain: boolean;
}
/**
 * Metadata from the built `.ctrie` file, populated after loading.
 * All values are derived from the binary header and the manifest.json
 * generated by `build_web_stress_db.py`.
 */
interface TrieStats {
    /** Total number of word forms stored in the trie. */
    wordCount: number;
    /** Total number of internal trie nodes. */
    nodeCount: number;
    /** Compressed file size in bytes (the `.ctrie.gz` you serve). */
    gzSizeBytes: number;
}
/** Ukrainian vowels (lowercase). */
type UkrainianVowel = "а" | "е" | "є" | "и" | "і" | "ї" | "о" | "у" | "ю" | "я";

/** Ukrainian vowels as a Set for fast membership checks. */
declare const UA_VOWELS: ReadonlySet<string>;
/** Correct Ukrainian apostrophe: U+02BC modifier letter apostrophe. */
declare const CORRECT_APOSTROPHE = "\u02BC";
/**
 * Normalise all apostrophe variants to U+02BC (modifier letter apostrophe),
 * which is the correct character per Ukrainian orthography.
 *
 * @example
 * normaliseApostrophe("п\u2019ять") // → "п\u02bcять"
 */
declare function normaliseApostrophe(text: string): string;
/**
 * Apply a combining acute accent (U+0301) after the `vowelIndex`-th
 * Ukrainian vowel (0-based count) in `word`.
 *
 * Returns the original word unchanged if `vowelIndex` is out of range.
 *
 * @example
 * applyStressMark('університет', 4) // → 'університе\u0301т'
 * applyStressMark('мама', 0)        // → 'ма\u0301ма'
 */
declare function applyStressMark(word: string, vowelIndex: number): string;
/** Internal: lowercase + normalise apostrophe + strip combining diacritics. */
declare function normWord(word: string): string;

/**
 * Offline Ukrainian word stress resolver backed by a compact binary trie.
 *
 * Lookup is **O(word_length)** and entirely in-memory — no network I/O after
 * the initial load.
 *
 * @example
 * ```ts
 * // Browser
 * const trie = await UaStressTrie.fromUrl('/static/ua_stress.ctrie.gz')
 *
 * // Node.js
 * const trie = await UaStressTrie.fromFile('./data/ua_stress.ctrie.gz')
 *
 * trie.lookup('університет')   // → 4
 * trie.mark('університет')     // → 'університе\u0301т'
 * trie.lookupFull('замок')     // → { stress: 0, stresses: [0, 1], type: 'heteronym', uncertain: true }
 * trie.lookupFull('помилка')   // → { stress: 0, stresses: [0, 1], type: 'variative', uncertain: true }
 * ```
 */
declare class UaStressTrie {
    private readonly _view;
    private readonly _charToId;
    private readonly _nodesOffset;
    private readonly _nodeCount;
    private readonly _wordCount;
    private readonly _alphaSize;
    private readonly _gzSizeBytes;
    private readonly _version;
    /** Per-variant morphological data loaded via `loadVariants()`. */
    private _variants;
    /**
     * Construct from a raw (already-decompressed) `.ctrie` `ArrayBuffer`.
     *
     * You normally don't call this directly — use a factory method instead.
     */
    constructor(buffer: ArrayBuffer, gzSizeBytes?: number);
    /**
     * Fetch a `.ctrie` or `.ctrie.gz` file and parse it into a `UaStressTrie`.
     *
     * Automatically detects and decompresses gzip data (works both with and
     * without `Content-Encoding: gzip` on the server).
     *
     * **Recommended serving setup** (avoids client-side decompression work):
     * ```
     * Content-Encoding: gzip
     * Content-Type: application/octet-stream
     * ```
     *
     * @param url - URL to `.ctrie.gz` (or raw `.ctrie`)
     */
    static fromUrl(url: string): Promise<UaStressTrie>;
    /**
     * Load from a local file path (**Node.js only**).
     *
     * Handles both `.ctrie.gz` (gzip-compressed) and raw `.ctrie` files.
     *
     * @param filePath - Absolute or relative path to the data file
     */
    static fromFile(filePath: string): Promise<UaStressTrie>;
    /**
     * Parse from an already-decompressed `ArrayBuffer`.
     *
     * Useful when you loaded the binary data yourself (e.g. from a Service
     * Worker cache, IndexedDB, or a custom fetch wrapper).
     *
     * @param buffer - Raw, decompressed `.ctrie` bytes
     */
    static fromBuffer(buffer: ArrayBuffer): UaStressTrie;
    /**
     * Load per-variant morphological data from `ua_stress.variants.json.gz`.
     *
     * After calling this, `lookupFull()` will populate the `variants` field for
     * all words with multiple stress positions (heteronyms and variatives).
     *
     * @example
     * // Browser
     * await trie.loadVariants('/static/ua_stress.variants.json.gz')
     *
     * // Node.js
     * import { readFileSync } from 'fs'
     * const gz = readFileSync('./data/ua_stress.variants.json.gz')
     * await trie.loadVariants(gz.buffer)
     */
    loadVariants(source: string | ArrayBuffer): Promise<void>;
    /**
     * Load variants from a Node.js file path (convenience wrapper).
     * Prefer `loadVariants(buffer)` in environments where you already have the bytes.
     */
    static loadVariantsFromFile(trie: UaStressTrie, filePath: string): Promise<void>;
    /** Whether per-variant morphological data has been loaded. */
    get variantsLoaded(): boolean;
    /** Total number of word forms stored in the trie. */
    get wordCount(): number;
    /** Total number of internal nodes (structural metric). */
    get nodeCount(): number;
    /** Metadata summary (wordCount, nodeCount, gzSizeBytes). */
    get stats(): TrieStats;
    /**
     * Look up the stressed vowel index (0-based) for a word.
     *
     * Returns `null` if the word is not in the trie — use an ONNX-based
     * fallback (e.g. Luscinia) for OOV words.
     *
     * Apostrophe variants and casing are normalised automatically.
     *
     * @example
     * trie.lookup('університет')   // → 4
     * trie.lookup('мама')          // → 0
     * trie.lookup('unknownword')   // → null
     */
    lookup(word: string): number | null;
    /**
     * Full lookup returning all stress positions and type classification.
     *
     * @returns `LookupResult` or `null` if the word is not in the database.
     *
     * The `type` field tells you how to interpret multiple stress positions:
     *
     * - `"unique"`    — one stress, no ambiguity.
     * - `"variative"` — both positions in `stresses[]` are orthographically
     *                    valid simultaneously (e.g. _по́милка_ / _поми́лка_).
     *                    Present both to the user, or pick either — both are correct.
     * - `"heteronym"` — different positions correspond to different meanings
     *                    or grammatical forms (e.g. _за́мок_ "lock" vs _замо́к_ "castle";
     *                    _бло́хи_ gen.sg vs _блохи́_ nom.pl).
     *                    Context-aware disambiguation is needed to pick the right one.
     *
     * @example
     * trie.lookupFull('університет')
     * // → { stress: 4, stresses: [4], type: 'unique', uncertain: false }
     *
     * trie.lookupFull('помилка')
     * // → { stress: 0, stresses: [0, 1], type: 'variative', uncertain: true }
     *
     * trie.lookupFull('замок')
     * // → { stress: 0, stresses: [0, 1], type: 'heteronym', uncertain: true }
     *
     * trie.lookupFull('xyz123')
     * // → null
     */
    lookupFull(word: string): LookupResult | null;
    /**
     * Return the word with a combining acute accent (U+0301) on the stressed
     * vowel, or `null` if the word is not in the trie.
     *
     * The accent is inserted *after* the stressed vowel so it renders correctly
     * in all Unicode-compliant environments.
     *
     * @example
     * trie.mark('університет') // → 'університе\u0301т'
     * trie.mark('мама')        // → 'ма\u0301ма'
     * trie.mark('xyz123')      // → null
     */
    mark(word: string): string | null;
    /**
     * Batch `lookup` — stress index for each word.  Returns `null` for unknowns.
     *
     * Prefer this over calling `lookup()` in a loop: a single method call
     * avoids repeated property lookups and is easier to pipeline.
     *
     * @example
     * trie.lookupBatch(['мама', 'тато', 'xyz'])  // → [0, 0, null]
     */
    lookupBatch(words: string[]): (number | null)[];
    /** Alias for {@link lookupBatch}. */
    lookupMany(words: string[]): (number | null)[];
    /**
     * Batch `lookupFull` — full result for each word.  Returns `null` for unknowns.
     *
     * @example
     * trie.lookupFullBatch(['замок', 'xyz'])
     * // → [{ stress: 0, stresses: [0,1], type: 'heteronym', uncertain: true }, null]
     */
    lookupFullBatch(words: string[]): (LookupResult | null)[];
    /** Alias for {@link lookupFullBatch}. */
    lookupFullMany(words: string[]): (LookupResult | null)[];
    /**
     * Batch `mark` — returns each word with an acute accent on the stressed vowel,
     * or `null` for words not in the dictionary.
     *
     * @example
     * trie.markBatch(['мама', 'університет', 'xyz'])
     * // → ['ма\u0301ма', 'університе\u0301т', null]
     */
    markBatch(words: string[]): (string | null)[];
    /** Alias for {@link markBatch}. */
    markMany(words: string[]): (string | null)[];
    private _nodeByte;
    private _firstChild;
    /**
     * Find the child of `parentIdx` whose char_id equals `targetId`.
     *
     * Children are contiguous in BFS order and sorted by char_id (ascending),
     * so we stop early when `char_id > targetId`.
     *
     * Returns the child node index, or -1 if not found.
     */
    private _findChild;
}

export { CORRECT_APOSTROPHE, type LookupResult, type StressVariant, type TrieStats, UA_VOWELS, UaStressTrie, type UkrainianVowel, applyStressMark, normWord, normaliseApostrophe };
