import { type array, type describe, type Key, type listable } from "@ark/util";
import { BaseConstraint } from "../constraint.ts";
import type { GettableKeyOrNode, KeyOrKeyNode } from "../node.ts";
import type { Morph } from "../roots/morph.ts";
import { type BaseRoot } from "../roots/root.ts";
import type { BaseScope } from "../scope.ts";
import { type NodeCompiler } from "../shared/compile.ts";
import type { BaseNormalizedSchema, declareNode } from "../shared/declare.ts";
import { type nodeImplementationOf, type StructuralKind } from "../shared/implement.ts";
import type { JsonSchema } from "../shared/jsonSchema.ts";
import { type RegisteredReference } from "../shared/registry.ts";
import { ToJsonSchema } from "../shared/toJsonSchema.ts";
import { type InternalTraversal, type TraversalKind, type TraverseAllows, type TraverseApply } from "../shared/traversal.ts";
import { makeRootAndArrayPropertiesMutable } from "../shared/utils.ts";
import type { Index } from "./index.ts";
import { Optional } from "./optional.ts";
import type { Prop } from "./prop.ts";
import type { Required } from "./required.ts";
import type { Sequence } from "./sequence.ts";
/**
 * - `"ignore"` (default) - allow and preserve extra properties
 * - `"reject"` - disallow extra properties
 * - `"delete"` - clone and remove extra properties from output
 */
export type UndeclaredKeyBehavior = "ignore" | UndeclaredKeyHandling;
export type UndeclaredKeyHandling = "reject" | "delete";
export declare namespace Structure {
    interface Schema extends BaseNormalizedSchema {
        readonly optional?: readonly Optional.Schema[];
        readonly required?: readonly Required.Schema[];
        readonly index?: readonly Index.Schema[];
        readonly sequence?: Sequence.Schema;
        readonly undeclared?: UndeclaredKeyBehavior;
    }
    interface Inner {
        readonly optional?: readonly Optional.Node[];
        readonly required?: readonly Required.Node[];
        readonly index?: readonly Index.Node[];
        readonly sequence?: Sequence.Node;
        readonly undeclared?: UndeclaredKeyHandling;
    }
    namespace Inner {
        type mutable = makeRootAndArrayPropertiesMutable<Inner>;
    }
    interface Declaration extends declareNode<{
        kind: "structure";
        schema: Schema;
        normalizedSchema: Schema;
        inner: Inner;
        prerequisite: object;
        childKind: StructuralKind;
    }> {
    }
    type Node = StructureNode;
}
export declare class StructureNode extends BaseConstraint<Structure.Declaration> {
    impliedBasis: BaseRoot;
    impliedSiblings: BaseConstraint<import("../constraint.ts").Constraint.Declaration>[];
    props: array<Prop.Node>;
    propsByKey: Record<Key, Prop.Node | undefined>;
    propsByKeyReference: RegisteredReference;
    expression: string;
    requiredKeys: Key[];
    optionalKeys: Key[];
    literalKeys: Key[];
    _keyof: BaseRoot | undefined;
    keyof(): BaseRoot;
    map(flatMapProp: PropFlatMapper): StructureNode;
    assertHasKeys(keys: array<KeyOrKeyNode>): void;
    get(indexer: GettableKeyOrNode, ...path: array<GettableKeyOrNode>): BaseRoot;
    pick(...keys: KeyOrKeyNode[]): StructureNode;
    omit(...keys: KeyOrKeyNode[]): StructureNode;
    optionalize(): StructureNode;
    require(): StructureNode;
    merge(r: StructureNode): StructureNode;
    private filterKeys;
    traverseAllows: TraverseAllows<object>;
    traverseApply: TraverseApply<object>;
    protected _traverse: (traversalKind: TraversalKind, data: object, ctx: InternalTraversal) => boolean;
    get defaultable(): Optional.Node.withDefault[];
    declaresKey: (k: Key) => boolean;
    _compileDeclaresKey(js: NodeCompiler): string;
    get structuralMorph(): Morph | undefined;
    structuralMorphRef: RegisteredReference | undefined;
    compile(js: NodeCompiler): unknown;
    protected compileExhaustiveEntry(js: NodeCompiler): NodeCompiler;
    reduceJsonSchema(schema: JsonSchema.Structure, ctx: ToJsonSchema.Context): JsonSchema.Structure;
    reduceObjectJsonSchema(schema: JsonSchema.Object, ctx: ToJsonSchema.Context): JsonSchema.Object;
}
export type PropFlatMapper = (entry: Prop.Node) => listable<MappedPropInner>;
export type MappedPropInner = BaseMappedPropInner | OptionalMappedPropInner;
export interface BaseMappedPropInner extends Required.Schema {
    kind?: "required" | "optional";
}
export interface OptionalMappedPropInner extends Optional.Schema {
    kind: "optional";
}
export declare const Structure: {
    implementation: nodeImplementationOf<Structure.Declaration>;
    Node: typeof StructureNode;
};
export declare const writeNumberIndexMessage: (indexExpression: string, sequenceExpression: string) => string;
export type NormalizedIndex = {
    index?: Index.Node;
    required?: Required.Node[];
    optional?: Optional.Node[];
};
/** extract enumerable named props from an index signature */
export declare const normalizeIndex: (signature: BaseRoot, value: BaseRoot, $: BaseScope) => NormalizedIndex;
export declare const typeKeyToString: (k: KeyOrKeyNode) => string;
export declare const writeInvalidKeysMessage: <o extends string, keys extends array<KeyOrKeyNode>>(o: o, keys: keys) => string;
export declare const writeDuplicateKeyMessage: <key extends Key>(key: key) => writeDuplicateKeyMessage<key>;
export type writeDuplicateKeyMessage<key extends Key> = `Duplicate key '${describe<key>}'`;
