import { type U } from "../utils";
import { type MutGraph } from ".";
import { type Id } from "./utils";
/**
 * An operator that creates node data from an id
 *
 * The index passed in is the edge index where the id is first seen.
 */
export type IdNodeDatum<out D = unknown> = (id: string, index: number) => D;
/**
 * The operators that parametrize {@link Connect}
 */
export interface ConnectOps<out N = unknown, in L = never> {
    /** the source id operator */
    sourceId: Id<L>;
    /** the target id operator */
    targetId: Id<L>;
    /** the node datum operator */
    nodeDatum: IdNodeDatum<N>;
}
/**
 * The constraint applied to data passed into {@link Connect}
 * conditioned on its operators.
 */
type ConnectLinkDatum<Ops extends ConnectOps> = Ops extends ConnectOps<unknown, infer L> ? L : never;
/**
 * an operator that constructs a {@link MutGraph} from link data.
 *
 * Create a default connect operator with {@link graphConnect}. The accessor for the
 * {@link sourceId | source id string}, {@link targetId | target id string},
 * and whether to allow {@link single} nodes can all be modified.
 *
 * Links in the dag will have the same data as the objects passed in, and nodes
 * will have the ids referenced as either the source or the target.
 */
export interface Connect<NodeDatum, Ops extends ConnectOps<NodeDatum>> {
    /**
     * convert connect data into a graph
     *
     * @param data - an array of each connection
     * @returns grf - the resulting graph
     */
    <L extends ConnectLinkDatum<Ops>>(data: readonly L[]): MutGraph<NodeDatum, L>;
    /**
     * set the source id accessor
     *
     * Sets the source accessor to the given {@link Id} and returns this
     * Connect. This should return the source id of the link
     * data. The default accessor is:
     *
     * ```ts
     * ([source, ]) => source
     * ```
     */
    sourceId<NewId extends Id>(id: NewId): Connect<NodeDatum, U<Ops, "sourceId", NewId>>;
    /** Gets the current sourceId accessor. */
    sourceId(): Ops["sourceId"];
    /**
     * set the target id accessor
     *
     * Sets the target accessor to the given {@link Id} and returns this
     * Connect. This should return the target id of the link
     * data. The default accessor is:
     *
     * ```ts
     * ([, target]) => target
     * ```
     */
    targetId<NewId extends Id>(id: NewId): Connect<NodeDatum, U<Ops, "targetId", NewId>>;
    /** Gets the current targetId accessor. */
    targetId(): Ops["targetId"];
    /**
     * set the node datum accessor
     *
     * Sets the id node datum accessor to the given {@link IdNodeDatum} and
     * returns this Connect. This function allows you to decide what data to
     * attach to nodes created via the connect method. The default is just the id
     * string.
     *
     * ```ts
     * (data) => data
     * ```
     */
    nodeDatum<NewNodeDatum, NewNodeDatumOp extends IdNodeDatum<NewNodeDatum>>(data: NewNodeDatumOp & IdNodeDatum<NewNodeDatum>): Connect<NewNodeDatum, U<Ops, "nodeDatum", NewNodeDatumOp>>;
    /** Get the current id node datum operator */
    nodeDatum(): Ops["nodeDatum"];
    /**
     * set the single node allowance
     *
     * Sets the allowance for single nodes. If enabled and the source id equals
     * the target id, then a single node with no parents will be created.
     * Otherwise a self loop will be created which will result in an error. Note
     * only single nodes without parents or children need to be specified this
     * way, otherwise any other connection to a node will create it.
     *
     * (default: `false`)
     */
    single(val: boolean): Connect<NodeDatum, Ops>;
    /** get the current single node setting. */
    single(): boolean;
}
/** default interface for tuples that start with a string */
export interface HasZeroString {
    /** the zero property */
    readonly 0: string;
}
/** default interface for functions whose second element is a string */
export interface HasOneString {
    /** the one property */
    readonly 1: string;
}
/** the default connect operator */
export type DefaultConnect = Connect<string, {
    /** the default source id operator */
    sourceId: Id<HasZeroString>;
    /** the default target id operator */
    targetId: Id<HasOneString>;
    /** the default node datum operator */
    nodeDatum: IdNodeDatum<string>;
}>;
/**
 * create a new {@link Connect} with default settings
 *
 * Connect operators create graphs from link data that contains ids to source
 * and target nodes. By default it expects link data that are tuples of the
 * source and target id as strings.
 *
 * @example
 *
 * If you want to build a graph with the default settings:
 *
 * ```ts
 * const data = [
 *   ["Euler", "Lagrange"],
 *   ["Lagrange", "Fourier"],
 *   ["Lagrange", "Poisson"],
 *   ["Fourier", "Dirichlet"],
 *   ["Poisson", "Dirichlet"],
 * ] as const;
 *
 * const builder = graphConnect();
 * const grf = builder(data);
 * ```
 *
 * @example
 *
 * If you want to use custom data:
 *
 * ```ts
 * const data = [
 *   { source: "Euler", target: "Lagrange" },
 *   { source: "Lagrange", target: "Fourier" },
 * ] as const;
 *
 * const builder = graphConnect()
 *   .sourceId(({ source }: { source: string }) => source)
 *   .targetId(({ target }: { target: string }) => target);
 * const grf = builder(data);
 * ```
 */
export declare function graphConnect(...args: never[]): DefaultConnect;
export {};
