import * as Effect from 'effect/Effect';
import type * as Types from 'effect/Types';
import { type GuardedType, type MaybePromise, type Position } from '@dxos/util';
import { type PluginContext } from '../core';
import { type AnyIntentChain, type Intent, type IntentChain, type IntentData, type IntentParams, type IntentResultData, type IntentSchema, type Label } from './intent';
/**
 * The return value of an intent effect.
 */
export type IntentEffectResult<Input, Output> = {
    /**
     * The output of the action that was performed.
     *
     * If the intent is apart of a chain of intents, the data will be passed to the next intent.
     */
    data?: Output;
    /**
     * If provided, the action will be undoable.
     */
    undoable?: {
        /**
         * Message to display to the user when indicating that the action can be undone.
         */
        message: Label;
        /**
         * Will be merged with the original intent data when firing the undo intent.
         */
        data?: Partial<Input>;
    };
    /**
     * An error that occurred while performing the action.
     *
     * If the intent is apart of a chain of intents and an error occurs, the chain will be aborted.
     *
     * Return caught error instead of throwing to trigger other intent to be triggered prior to returning the error.
     */
    error?: Error;
    /**
     * Other intent chains to be triggered.
     */
    intents?: AnyIntentChain[];
};
export type AnyIntentEffectResult = IntentEffectResult<any, any>;
/**
 * The result of an intent dispatcher.
 */
export type IntentDispatcherResult<Input, Output> = Pick<IntentEffectResult<Input, Output>, 'data' | 'error'>;
/**
 * The implementation of an intent effect.
 */
export type IntentEffectDefinition<Input, Output> = (data: Input, undo: boolean) => MaybePromise<IntentEffectResult<Input, Output> | void> | Effect.Effect<IntentEffectResult<Input, Output> | void, Error>;
/**
 * Intent resolver to match intents to their effects.
 */
export type IntentResolver<Tag extends string, Fields extends IntentParams, Data = IntentData<Fields>> = Readonly<{
    /**
     * The schema of the intent to be resolved.
     */
    intent: IntentSchema<Tag, Fields>;
    /**
     * Hint to determine the order the resolvers are processed if multiple resolvers are defined for the same intent.
     * Only one resolver will be used.
     */
    position?: Position;
    /**
     * Optional filter to determine if the resolver should be used.
     */
    filter?: (data: IntentData<Fields>) => data is Data;
    /**
     * The effect to be performed when the intent is resolved.
     */
    resolve: IntentEffectDefinition<GuardedType<IntentResolver<Tag, Fields, Data>['filter']>, IntentResultData<Fields>>;
}>;
export type AnyIntentResolver = IntentResolver<any, any, any>;
/**
 * Creates an intent resolver to match intents to their effects.
 * @param schema Schema of the intent. Must be a tagged class with input and output schemas.
 * @param effect Effect to be performed when the intent is resolved.
 * @param params.disposition Determines the priority of the resolver when multiple are resolved.
 * @param params.filter Optional filter to determine if the resolver should be used.
 */
export declare const createResolver: <Tag extends string, Fields extends IntentParams, Data = IntentData<Fields>>(resolver: IntentResolver<Tag, Fields, Data>) => Readonly<{
    /**
     * The schema of the intent to be resolved.
     */
    intent: IntentSchema<Tag, Fields>;
    /**
     * Hint to determine the order the resolvers are processed if multiple resolvers are defined for the same intent.
     * Only one resolver will be used.
     */
    position?: Position;
    /**
     * Optional filter to determine if the resolver should be used.
     */
    filter?: ((data: IntentData<Fields>) => data is Data) | undefined;
    /**
     * The effect to be performed when the intent is resolved.
     */
    resolve: IntentEffectDefinition<Data, IntentResultData<Fields>>;
}>;
/**
 * Invokes intents and returns the result.
 */
export type PromiseIntentDispatcher = <Fields extends IntentParams>(intent: IntentChain<any, any, any, Fields>) => Promise<Types.Simplify<IntentDispatcherResult<IntentData<Fields>, IntentResultData<Fields>>>>;
/**
 * Creates an effect for intents.
 */
export type IntentDispatcher = <Fields extends IntentParams>(intent: IntentChain<any, any, any, Fields>, depth?: number) => Effect.Effect<Types.Simplify<Required<IntentDispatcherResult<IntentData<Fields>, IntentResultData<Fields>>>['data']>, Error>;
type IntentResult<Tag extends string, Fields extends IntentParams> = IntentEffectResult<IntentData<Fields>, IntentResultData<Fields>> & {
    _intent: Intent<Tag, Fields>;
};
export type AnyIntentResult = IntentResult<any, any>;
/**
 * Invokes the most recent undoable intent with undo flags.
 */
export type PromiseIntentUndo = () => Promise<IntentDispatcherResult<any, any>>;
/**
 * Creates an effect which undoes the last intent.
 */
export type IntentUndo = () => Effect.Effect<any, Error>;
export type IntentContext = {
    dispatch: IntentDispatcher;
    dispatchPromise: PromiseIntentDispatcher;
    undo: IntentUndo;
    undoPromise: PromiseIntentUndo;
};
/**
 * Sets of an intent dispatcher.
 *
 * @param getResolvers A function that returns an array of available intent resolvers.
 * @param params.historyLimit The maximum number of intent results to keep in history.
 * @param params.executionLimit The maximum recursion depth of intent chains.
 */
export declare const createDispatcher: (getResolvers: () => AnyIntentResolver[], { executionLimit, historyLimit }?: {
    executionLimit?: number | undefined;
    historyLimit?: number | undefined;
}) => IntentContext;
declare const _default: (context: PluginContext) => import("..").Capability<import("..").InterfaceDef<IntentContext>>;
export default _default;
//# sourceMappingURL=intent-dispatcher.d.ts.map