import { EngineContext } from ".";
import { DatastoreInstance } from "./db";
import { GraphNodeType } from "./graph";
import { PathType } from "./macro";
import { ViewInstance } from "./view";
export declare enum OperationTypes {
    GET = "GET",
    OBSERVE = "OBSERVE",
    UPDATE = "UPDATE",
    REF = "REF",
    FUNC = "FUNC",
    STRUCT = "STRUCT",
    VALUE = "VALUE",
    CONSTRUCTOR = "CONSTRUCTOR",
    PASSTHROUGH = "PASSTHROUGH"
}
export declare enum ValueTypes {
    CONST = "CONST",
    EXTERNAL = "EXTERNAL",
    INTERNAL = "INTERNAL",
    INVOKE = "INVOKE",
    REFINEE = "REFINEE"
}
export interface ConstValue {
    type: ValueTypes.CONST;
    value: any;
}
export interface ExternalValue {
    type: ValueTypes.EXTERNAL;
    path: string[];
}
export interface InternalValue {
    type: ValueTypes.INTERNAL;
    path: string[];
}
export interface InvokeValue {
    type: ValueTypes.INVOKE;
    path: string[];
}
export declare type RefiningValueArg = ConstValue | ExternalValue | InternalValue;
export interface RefiningValue {
    type: ValueTypes.REFINEE;
    value: {
        type: AccessMethods | UpdateMethods;
        args: RefiningValueArg[];
    };
}
export declare type StaticValue = ConstValue | ExternalValue | InternalValue | RefiningValue;
export declare type InvokableValue = StaticValue | InvokeValue | RefiningValue;
export declare type StaticPath = StaticValue[];
export declare type InvokablePath = InvokableValue[];
export interface BaseOperation {
    meta?: any;
}
export interface GetOperation extends BaseOperation {
    type: OperationTypes.GET;
    path: InvokableValue[];
}
export interface ConstructorOperation extends BaseOperation {
    type: OperationTypes.CONSTRUCTOR;
    value: PathType.OBSERVE | PathType.GET | PathType.UPDATE;
}
export interface UpdateOperation extends BaseOperation {
    type: OperationTypes.UPDATE;
    path: InvokableValue[];
}
export interface ObserveOperation extends BaseOperation {
    type: OperationTypes.OBSERVE;
    path: StaticValue[];
}
export declare type StaticOperation = ObserveOperation | ValueOperation;
export interface FuncOperation extends BaseOperation {
    type: OperationTypes.FUNC;
    value: {
        params: StaticOperation[];
        fn: (...param: any) => any;
    };
}
export interface StructOperation extends BaseOperation {
    type: OperationTypes.STRUCT;
    value: {
        [key: string]: Operation;
    };
}
export interface PassthroughOperation extends BaseOperation {
    type: OperationTypes.PASSTHROUGH;
}
export interface ValueOperation extends BaseOperation {
    type: OperationTypes.VALUE;
    value: ExternalValue | InternalValue | ConstValue;
}
export declare type Operation = GetOperation | ObserveOperation | UpdateOperation | FuncOperation | StructOperation | ValueOperation | ConstructorOperation | PassthroughOperation;
export interface ProducerProps {
    [key: string]: Operation;
}
export declare type PrivateProps<Props = any> = {
    _now: () => number;
    _producerId: string;
    _viewId: string;
    _props: Props;
};
export declare type ProducerCb = () => void;
export declare type Producer = (props: any) => void | ProducerCb | Promise<void | ProducerCb>;
export interface ProducerMeta {
    name?: string;
    location?: {
        start: {
            line: number;
            column: number;
        };
        end: {
            line: number;
            column: number;
        };
    };
    absoluteFilePath?: string;
    absoluteRootPath?: string;
    relativeFilePath?: string;
}
export interface ProducerConfig {
    sourceId?: string;
    buildId?: string;
    meta?: ProducerMeta;
    props: StructOperation | PassthroughOperation;
    fn: Producer;
}
export interface ProducerInstance {
    id: string;
    sourceId: string;
    mount: () => void;
    unmount: () => void;
    updateExternal: (props: ProducerContext["props"]) => this;
}
export interface ExternalProps {
    [key: string]: any;
}
export interface ProducerContext {
    emit: EngineContext["emit"];
    db: DatastoreInstance;
    props?: ExternalProps;
    keepReferences?: string[];
    serializers?: ValueSerializer[];
    debug?: boolean;
    addView?: (view: ViewInstance) => void;
}
export declare type OperationParams = {
    [k: string]: OperationParams | string | number | void | null;
};
export declare type Params<T> = {
    [k in keyof T]: string | number | Params<T[k]>;
};
export declare enum UpdateMethods {
    set = "set",
    merge = "merge",
    remove = "remove",
    push = "push",
    pop = "pop"
}
export declare type UpdateValue<T = any, P = {}> = {
    [UpdateMethods.set]: (value: T, params?: Params<P>) => void;
    [UpdateMethods.merge]: (value: Partial<T>, params?: Params<P>) => void;
    [UpdateMethods.remove]: (params?: Params<P>) => void;
    [UpdateMethods.push]: (value: T extends (infer R)[] ? R : unknown, params?: Params<P>) => void;
    [UpdateMethods.pop]: (params?: Params<P>) => void;
};
export declare enum AccessMethods {
    value = "value",
    includes = "includes",
    length = "length",
    isObserved = "isObserved"
}
export declare type GetValue<T = any, P = {}> = {
    [AccessMethods.value]: (params?: Params<P>) => T;
    [AccessMethods.includes]: (value: any, params?: Params<P>) => boolean;
    [AccessMethods.length]: (params?: Params<P>) => number;
    [AccessMethods.isObserved]: (params?: Params<P>) => boolean;
};
export declare type ObservePath<T> = T;
export declare type UpdatePath<T> = any;
export declare type GetPath<T> = any;
export declare type Prop = any;
export declare type Param = any;
export declare type Arg = any;
export declare type ValueSerializer = {
    type?: GraphNodeType;
    name?: string;
    instanceof?: any;
    serializer: (value: any) => void | string;
};
export declare type ProducersList = undefined | Producer | Producer[] | ProducersList[] | {
    [k: string]: ProducersList;
};
