import { GraphSchema } from '../schemas/index.js';
import { Edge } from '../programmatic/edge.js';
import { ILogger } from './interfaces.js';
import { Input } from '../programmatic/input.js';
import { Node } from '../programmatic/node.js';
import { Output } from '../programmatic/output.js';
import type { ExternalLoader, NodeRun, NodeStart } from '../types.js';
import type { NodeFactory, SerializedGraph } from './types.js';
export type CapabilityFactory = {
    name: string;
    register: (graph: Graph) => any;
    version?: string;
};
export type InputDefinition = {
    value: any;
    type?: GraphSchema;
};
export type GraphExecuteOptions = {
    /**
     * Throws an error if the input/output nodes are not found
     */
    strict?: boolean;
    inputs?: Record<string, InputDefinition>;
    /**
     * Whether to track and emit stats as part of the execution
     */
    stats?: boolean;
    /**
     * Whether to provide a journal of the execution
     */
    journal?: boolean;
};
export type EdgeOpts = {
    id: string;
    source: string;
    target: string;
    sourceHandle: string;
    targetHandle: string;
    /**
     * Any additional data to be stored on the edge
     */
    annotations?: Record<string, any>;
    /**
     * Whether to automatically update the graph when the state changes or to wait for an explicit call to update
     */
    noPropagate?: boolean;
};
export type FinalizerType = 'serialize' | 'output';
export type FinalizerLookup = {
    serialize: SerializedGraph;
    output: any;
};
export type SubscriptionLookup = {
    nodeAdded: Node;
    nodeRemoved: string;
    edgeAdded: Edge;
    edgeRemoved: string;
    nodeUpdated: Node;
    edgeUpdated: Edge;
    start: object;
    stop: object;
    pause: object;
    resume: object;
    edgeIndexUpdated: Edge;
    valueSent: Edge[];
    nodeExecuted: NodeRun;
    nodeStarted: NodeStart;
};
export type ListenerType<T> = [T] extends [(...args: infer U) => any] ? U : [T] extends [void] ? [] : [T];
export type SubscriptionExecutor<T extends keyof SubscriptionLookup> = (data: SubscriptionLookup[T]) => void;
export type SerializerType<T extends keyof FinalizerLookup> = FinalizerLookup[T];
export type FinalizerExecutor<Type extends keyof FinalizerLookup> = (value: SerializerType<Type>) => SerializerType<Type>;
export type PlayState = 'playing' | 'paused' | 'stopped';
export interface IGraph {
    /**
     * Whether to automatically update the graph when the state changes or to wait for an explicit call to update
     */
    autoUpdate?: boolean;
    annotations?: Record<string, any>;
}
export interface IUpdateOpts {
    /**
     * If true, no memoization will be performed
     */
    noMemo?: boolean;
    /**
     * If true, the update will not be propagated to the successor nodes
     */
    noRecursive?: boolean;
    /**
     * If true, we won't compare the input values to see if the node needs to be updated
     */
    noCompare?: boolean;
}
export interface StatRecord {
    start: number;
    end: number;
    error?: Error;
}
export interface BatchExecution {
    start: number;
    end: number;
    stats?: Record<string, StatRecord>;
    order: string[];
    output?: {
        [key: string]: {
            value: any;
            type: GraphSchema;
        };
    };
}
/**
 * This is our internal graph representation that we use to perform transformations on
 */
export declare class Graph {
    private finalizers;
    private listeners;
    annotations: Record<string, any>;
    nodes: Record<string, Node>;
    edges: Record<string, Edge>;
    capabilities: Record<string, any>;
    logger: ILogger;
    messageQueue: {
        eventName: string;
        data: any;
        origin: Node;
    }[];
    externalLoader?: ExternalLoader;
    /**
     * Outgoing edges from a node as an array of edgeIds
     * First key is the source node
     * Values are the edgeIds
     */
    successorNodes: Record<string, string[]>;
    constructor(input?: IGraph);
    /**
     * Meant to be used internally by nodes to load resources
     * @param uri
     * @param node
     * @param data
     * @returns
     */
    loadResource(uri: string, node: Node, data?: any): Promise<any>;
    /**
     * Connects two nodes together. If the target is variadic, it will automatically add the index to the edge data if not provided
     * @param source
     * @param sourceHandle
     * @param target
     * @param targetHandle
     * @param variadicIndex
     * @returns
     */
    connect(source: Node, sourceHandle: Output, target: Node, targetHandle: Input, variadicIndex?: number): Edge;
    /**
     * Checks to see if there exists any connection for an input
     * @param source
     * @param port
     * @returns
     */
    hasConnectedInput(source: Node, input: Input): boolean;
    /**
     * Clears the graph
     */
    clear(): void;
    addNode(node: Node): void;
    /**
     * Removes a node from the graph and disconnects all the edges.
     * @param nodeId
     * @returns true if the node was removed, false if the node was not found
     */
    removeNode(nodeId: string): boolean;
    removeEdge(edgeId: string): void;
    /**
     * Retrieves a flat list of all the nodes ids in the graph
     * @returns
     */
    getNodeIds(): string[];
    /**
     * Will forcefully update a node in the graph. This will also update all the edges that are connected to the node recursively
     * @throws[Error] if the node is not found
     * @param nodeID
     */
    update(nodeID: string, opts?: IUpdateOpts): Promise<void>;
    /**
     * Serialize the graph for transport
     * @returns
     */
    serialize(): SerializedGraph;
    /**
     * Extracts the nodes types from a serialized graph
     * @param graph
     */
    static extractTypes(graph: SerializedGraph): string[];
    checkCapabilitites(annotations: Record<string, any>): void;
    /**
     * Creates a graph from a serialized graph. Note that the types of the nodes must be present in the lookup.
     * @param input
     * @param lookup
     */
    deserialize(serialized: SerializedGraph, lookup: Record<string, NodeFactory>): Promise<Graph>;
    registerCapability(factory: CapabilityFactory): void;
    clone(): Graph;
    private forEachNode;
    /**
     * Starts the graph in network mode
     * TODO Complete
     */
    start: () => void;
    /**
     * Stops the graph in network mode
     */
    stop: () => void;
    pause: () => void;
    resume: () => void;
    /**
     * Triggers a message on the graph
     * TODO Complete
     * @param eventName
     * @param data
     * @param origin
     */
    trigger: (eventName: string, data: any, origin: Node) => void;
    /**
     * Executes the graph as a single batch. This will execute all the nodes in the graph and return the output of the output node
     * @param opts
     * @throws {BatchRunError}
     * @returns
     */
    execute(opts?: GraphExecuteOptions): Promise<BatchExecution>;
    /**
     * Returns the ids of the node that are immediate successors of the given node. O(m) the amount of edges
     * @param nodeId
     * @returns
     */
    successors(nodeId: any): Node[];
    /**
     * Returns the ids of the node that are immediate predecessors of the given node O(m) the amount of edges
     * @param nodeId
     * @returns
     */
    predecessors(nodeId: string): Node[];
    /**
     * Triggers a ripple effect on the graph starting from the given edge
     * @returns
     */
    ripple(output: Output): void;
    /**
     * Triggers the execution of the node and updates the successor nodes
     * @param nodeId
     * @param oneShot
     * @returns
     */
    propagate(nodeId: string, oneShot?: boolean): Promise<void>;
    /**
     * Creates an edge connection between two nodes
     * @param source
     * @param target
     * @param data
     */
    createEdge(opts: EdgeOpts): Edge;
    /**
     * Return all edges that point into the nodes inputs.
     * O(m) the amount of edges
     */
    inEdges(nodeId: string, sourceHandle?: string): Edge[];
    /**
     * Return all edges that are pointed out by node v.
     * O(m) the amount of edges
     */
    outEdges(nodeId: string, targetHandle?: string): Edge[];
    /**
     * Looks up a node by its id
     * @param nodeId
     * @returns
     */
    getNode(nodeId: string): Node | undefined;
    /**
     * Looks up an edge by its id
     * @param edgeId
     * @returns
     */
    getEdge(edgeId: string): Edge | undefined;
    emit<P extends keyof SubscriptionLookup = keyof SubscriptionLookup>(type: P, data: SubscriptionLookup[P]): void;
    on<P extends keyof SubscriptionLookup = keyof SubscriptionLookup>(type: P, listener: (...args: ListenerType<SubscriptionLookup[P]>) => void): () => void;
    onFinalize<T extends keyof FinalizerLookup = keyof FinalizerLookup>(type: T, listener: (...args: ListenerType<FinalizerLookup[T]>) => FinalizerLookup[T]): () => void;
}
//# sourceMappingURL=graph.d.ts.map