import { Component as Component_2 } from 'vue';
import { EmitsOptions } from 'vue';
import { MethodOptions } from 'vue';
import { Renderer } from 'vue';

export declare const ACTION_INSERT_CHILD = "insert-child";

declare const ACTION_INVOKE = "invoke";

export declare const ACTION_MOUNT = "mount";

export declare const ACTION_REMOVE_CHILD = "remove-child";

export declare const ACTION_UPDATE_PROPERTIES = "update-properties";

export declare const ACTION_UPDATE_TEXT = "update-text";

export declare interface Channel {
    <A extends RunnerAction>(action: A, ...payload: RunnerPayload<A>): void | Promise<void>;
}

export declare type ChildrenOf<Type> = Type extends SchemaType<string, Unknown, UnknownMethods, infer Children> ? Children : never;

declare type Component<Root extends RemoteRoot = RemoteRoot> = RemoteComponent<string, Root>;

export declare const createRemoteRenderer: <Root extends RemoteRoot<SchemaType<string, Unknown, UnknownMethods, UnknownType>> = RemoteRoot<SchemaType<string, Unknown, UnknownMethods, UnknownType>>>(root: Root) => Renderer<Root | Component<Root>>;

export declare const createRemoteRoot: <Supports extends RemoteComponentOption = RemoteComponentOption>(channel: Channel, options?: RemoteRootOptions<Supports>) => RemoteRoot<SchemaOf<Supports>>;

export declare const defineRemoteComponent: <Type extends string, Props extends Unknown = None, Methods extends UnknownMethods = None, Children extends SchemaType<string, Unknown> = never, Emits extends EmitsOptions | undefined = undefined>(type: Type | SchemaType<Type, Props, Methods, Children>, emits?: Emits | undefined, slots?: string[]) => Component_2<Unknown, Props, None, None, MethodOptions, Emits extends undefined ? None : Emits>;

declare type Id = string;

declare type IfAllKeysOptional<O, If, Else = never> = O extends None
? If
: NonOptionalKeys<O> extends { length: 0; }
? If
: Else

export declare const KIND_COMMENT = "comment";

export declare const KIND_COMPONENT = "component";

export declare const KIND_FRAGMENT = "fragment";

export declare const KIND_ROOT = "root";

export declare const KIND_TEXT = "text";

declare type MethodsOf<T> = T extends SchemaType<string, Unknown, infer Methods, SchemaType<string, Unknown>> ? Methods : never;

declare type None = Record<string, never>

declare type NonOptionalKeys<T> = {
    [K in keyof T]-?: undefined extends T[K] ? never : K;
}[keyof T]

export declare type PropertiesOf<T> = T extends SchemaType<string, infer Properties, UnknownMethods, SchemaType<string, Unknown>> ? Properties : None;

export declare interface RemoteComment<Root extends RemoteRoot = RemoteRoot> extends RemoteNode {
    readonly kind: typeof KIND_COMMENT;
    readonly root: Root;
    readonly progenitor: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
    readonly parent: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
    readonly text: string;
    update(text: string): void | Promise<void>;
    remove(): void | Promise<void>;
    serialize(): SerializedComment;
    print(): string;
}

export declare interface RemoteComponent<Type extends SupportedBy<RemoteRoot>, Root extends RemoteRoot = RemoteRoot> extends RemoteNode {
    readonly kind: typeof KIND_COMPONENT;
    readonly type: TypeOf<Type>;
    readonly root: Root;
    readonly progenitor: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
    readonly parent: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
    readonly properties: PropertiesOf<Type>;
    readonly children: ReadonlyArray<RemoteComment<Root> | RemoteComponent<ChildrenOf<Type>, Root> | RemoteText<Root>>;
    invoke(method: string, ...payload: unknown[]): Promise<unknown>;
    updateProperties(properties: Partial<PropertiesOf<Type>>): void | Promise<void>;
    append(...children: Array<RemoteComment<Root> | RemoteComponent<ChildrenOf<Type>, Root> | RemoteText<Root> | string>): void | Promise<void>;
    insertBefore(child: RemoteComment<Root> | RemoteComponent<ChildrenOf<Type>, Root> | RemoteText<Root>, before?: RemoteComment<Root> | RemoteComponent<ChildrenOf<Type>, Root> | RemoteText<Root> | null): void | Promise<void>;
    replace(...children: Array<RemoteComment<Root> | RemoteComponent<ChildrenOf<Type>, Root> | RemoteText<Root> | string>): void | Promise<void>;
    removeChild(child: RemoteComment<Root> | RemoteComponent<ChildrenOf<Type>, Root> | RemoteText<Root>): void | Promise<void>;
    remove(): void | Promise<void>;
    serialize(): SerializedComponent<PropertiesOf<Type>>;
    print(): string;
}

export declare interface RemoteComponentDescriptor<Type extends SupportedBy<RemoteRoot>> {
    type: Type;
    hasProperty(name: string | keyof PropertiesOf<Type>): name is keyof PropertiesOf<Type>;
    hasMethod(name: string | keyof MethodsOf<Type>): name is keyof MethodsOf<Type>;
    supports(name: string): boolean;
}

declare type RemoteComponentOption<Type extends SupportedBy<RemoteRoot> = SupportedBy<RemoteRoot>> = Type | RemoteComponentDescriptor<Type>;

export declare interface RemoteFragment<Root extends RemoteRoot = RemoteRoot> extends RemoteNode {
    readonly kind: typeof KIND_FRAGMENT;
    readonly root: Root;
    readonly progenitor: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
    readonly parent: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
    readonly children: ReadonlyArray<RemoteComment<Root> | RemoteComponent<SupportedBy<Root>, Root> | RemoteText<Root>>;
    append(...children: Array<RemoteComment<Root> | RemoteComponent<SupportedBy<Root>, Root> | RemoteText<Root> | string>): void | Promise<void>;
    insertBefore(child: RemoteComment<Root> | RemoteComponent<SupportedBy<Root>, Root> | RemoteText<Root>, before?: RemoteComment<Root> | RemoteComponent<SupportedBy<Root>, Root> | RemoteText<Root> | null): void | Promise<void>;
    replace(...children: Array<RemoteComment<Root> | RemoteComponent<SupportedBy<Root>, Root> | RemoteText<Root> | string>): void | Promise<void>;
    removeChild(child: RemoteComment<Root> | RemoteComponent<SupportedBy<Root>, Root> | RemoteText<Root>): void | Promise<void>;
    serialize(): SerializedFragment;
}

declare interface RemoteNode {
    readonly id: Id;
}

export declare interface RemoteRoot<Supports extends SchemaType<string, Unknown, UnknownMethods, UnknownType> = SchemaType<string, Unknown, UnknownMethods, UnknownType>> extends RemoteNode {
    readonly kind: typeof KIND_ROOT;
    readonly options: RemoteRootOptions<Supports>;
    readonly children: ReadonlyArray<RemoteComment<RemoteRoot<Supports>> | RemoteComponent<Supports, RemoteRoot<Supports>> | RemoteText<RemoteRoot<Supports>>>;
    append(...children: Array<RemoteComment<RemoteRoot<Supports>> | RemoteComponent<Supports, RemoteRoot<Supports>> | RemoteText<RemoteRoot<Supports>> | string>): void | Promise<void>;
    insertBefore(child: RemoteComment<RemoteRoot<Supports>> | RemoteComponent<Supports, RemoteRoot<Supports>> | RemoteText<RemoteRoot<Supports>>, before?: RemoteComment<RemoteRoot<Supports>> | RemoteComponent<Supports, RemoteRoot<Supports>> | RemoteText<RemoteRoot<Supports>> | null): void | Promise<void>;
    replace(...children: Array<RemoteComment<RemoteRoot<Supports>> | RemoteComponent<Supports, RemoteRoot<Supports>> | RemoteText<RemoteRoot<Supports>> | string>): void | Promise<void>;
    removeChild(child: RemoteComment<RemoteRoot<Supports>> | RemoteComponent<Supports, RemoteRoot<Supports>> | RemoteText<RemoteRoot<Supports>>): void | Promise<void>;
    createComment(text?: string): RemoteComment<RemoteRoot<Supports>>;
    createComponent<Type extends Supports>(type: Type | RemoteComponentDescriptor<Type>, ...rest: IfAllKeysOptional<PropertiesOf<Type>, [
    (PropertiesOf<Type> | null)?,
    ...Array<RemoteComment<RemoteRoot<Supports>> | RemoteComponent<ChildrenOf<Supports>, RemoteRoot<Supports>> | RemoteText<RemoteRoot<Supports>> | string>
    ] | [
    (PropertiesOf<Type> | null)?,
    Array<RemoteComment<RemoteRoot<Supports>> | RemoteComponent<ChildrenOf<Supports>, RemoteRoot<Supports>> | RemoteText<RemoteRoot<Supports>> | string>?
    ], [
    PropertiesOf<Type>,
    ...Array<RemoteComment<RemoteRoot<Supports>> | RemoteComponent<ChildrenOf<Supports>, RemoteRoot<Supports>> | RemoteText<RemoteRoot<Supports>> | string>
    ] | [
    PropertiesOf<Type>,
    Array<RemoteComment<RemoteRoot<Supports>> | RemoteComponent<ChildrenOf<Supports>, RemoteRoot<Supports>> | RemoteText<RemoteRoot<Supports>> | string>?
    ]>): RemoteComponent<Type, RemoteRoot<Supports>>;
    createFragment(): RemoteFragment<RemoteRoot<Supports>>;
    createText(text?: string): RemoteText<RemoteRoot<Supports>>;
    mount(): Promise<void>;
}

export declare interface RemoteRootOptions<Supports extends RemoteComponentOption = RemoteComponentOption> {
    readonly strict?: boolean;
    readonly components?: ReadonlyArray<Supports>;
}

export declare interface RemoteText<Root extends RemoteRoot = RemoteRoot> extends RemoteNode {
    readonly kind: typeof KIND_TEXT;
    readonly root: Root;
    readonly progenitor: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
    readonly parent: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
    readonly text: string;
    update(text: string): void | Promise<void>;
    serialize(): SerializedText;
    remove(): void | Promise<void>;
    print(): string;
}

export declare const ROOT_ID = "~";

declare interface Runner {
    mount(children: SerializedChild[]): void;
    insertChild(parentId: Id, after: number, child: SerializedChild, oldParentId: Id | false): void;
    removeChild(parentId: Id, at: number): void;
    updateProperties(id: Id, properties: Unknown): void;
    updateText(id: Id, text: string): void;
    invoke(id: Id, method: string, payload: unknown[], resolve: (result: unknown) => void, reject: (reason?: unknown) => void): void;
}

declare type RunnerAction = keyof RunnerActionMap;

declare interface RunnerActionMap {
    [ACTION_MOUNT]: Runner['mount'];
    [ACTION_INSERT_CHILD]: Runner['insertChild'];
    [ACTION_REMOVE_CHILD]: Runner['removeChild'];
    [ACTION_UPDATE_PROPERTIES]: Runner['updateProperties'];
    [ACTION_UPDATE_TEXT]: Runner['updateText'];
    [ACTION_INVOKE]: Runner['invoke'];
}

declare type RunnerPayload<T extends RunnerAction> = Parameters<RunnerActionMap[T]>;

declare interface Schema<Type extends string, Properties extends Unknown = None, Methods extends UnknownMethods = UnknownMethods, Children extends Schema<string, Unknown> = never> {
    readonly type?: Type;
    readonly properties?: Properties;
    readonly methods?: Methods;
    readonly children?: Children;
}

export declare type SchemaOf<D> = D extends RemoteComponentDescriptor<infer S1> ? S1 : D extends RemoteComponentOption<infer S2> ? S2 : never;

export declare type SchemaType<Type extends string, Properties extends Unknown = None, Methods extends UnknownMethods = UnknownMethods, Children extends SchemaType<string, Unknown> = never> = Type & Schema<Type, Properties, Methods, Children>;

declare type SerializedChild = SerializedComment | SerializedComponent | SerializedText;

declare interface SerializedComment {
    id: Id;
    kind: typeof KIND_COMMENT;
    text: string;
}

declare interface SerializedComponent<Properties extends Unknown = Unknown> {
    id: Id;
    kind: typeof KIND_COMPONENT;
    type: string;
    properties: Properties;
    children: SerializedChild[];
}

declare interface SerializedFragment {
    id: Id;
    kind: typeof KIND_FRAGMENT;
    children: SerializedChild[];
}

declare interface SerializedText {
    id: Id;
    kind: typeof KIND_TEXT;
    text: string;
}

export declare type SupportedBy<Root> = Root extends RemoteRoot<infer S> ? S : never;

export declare type TypeOf<T> = T extends SchemaType<infer Type, Unknown, UnknownMethods, SchemaType<string>> ? Type : never;

declare type Unknown = Record<string, unknown>

declare type UnknownMethods = Record<string, (...payload: unknown[]) => Promise<void>>

export declare type UnknownType = SchemaType<string, Unknown>;

export { }
