import { Attributes, CoreModel, CoreModelDefinition, FilterAttributes, ModelAction, ModelRef, ModelRefCustomProperties } from "./coremodel.js";
/**
 * Raw model without methods
 */
export type RawModel<T extends object> = {
    [K in Attributes<T>]?: T[K] extends object ? RawModel<T[K]> : T[K];
};
/**
 * Methods of an object
 *
 * Filter out attributes
 */
export type Methods<T extends object> = {
    [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
/**
 * Load related objects
 *
 * _K is not used but is required to complete the graph
 */
export type ModelRelated<T extends CoreModel, _K extends Attributes<T>> = {
    /**
     * Query the related objects
     * @param query
     * @returns
     */
    query: (query?: string) => Promise<{
        results: T[];
        continuationToken?: string;
    }>;
    /**
     *
     * @param model Iterate through all related objects
     * @returns
     */
    forEach: (model: T) => Promise<void>;
    /**
     * Get all object linked
     * @returns
     */
    getAll: () => Promise<T[]>;
};
export interface ModelLinker {
}
/**
 * Define a link to 1:n relation
 */
export declare class ModelLink<T extends CoreModel> implements ModelLinker {
    protected uuid: string;
    protected model: CoreModelDefinition<T>;
    protected parent: CoreModel;
    constructor(uuid: string, model: CoreModelDefinition<T>, parent?: CoreModel);
    get(): Promise<T>;
    set(id: string | T): void;
    toString(): string;
    toJSON(): string;
    getUuid(): string;
}
/**
 * Methods that allow to manage a collection of linked objects
 */
type ModelCollectionManager<T> = {
    /**
     * Add a linked object
     * @param model
     * @returns
     */
    add: (model: T) => void;
    /**
     * Remove a linked object
     * @param model the model to remove or its uuid
     * @returns
     */
    remove: (model: T | string) => void;
};
/**
 * Link to a collection of objects
 */
export declare class ModelLinksSimpleArray<T extends CoreModel> extends Array<ModelRef<T>> implements ModelLinker {
    protected model: CoreModelDefinition<T>;
    private parent;
    constructor(model: CoreModelDefinition<T>, content?: any[], parent?: CoreModel);
    add(model: string | ModelRef<T> | T): void;
    remove(model: ModelRef<T> | string | T): void;
}
/**
 * Link to a collection of objects including some additional data
 */
export declare class ModelLinksArray<T extends CoreModel, K> extends Array<ModelRefCustomProperties<T, (K & {
    uuid: string;
}) | {
    getUuid: () => string;
}>> implements ModelLinker {
    protected model: CoreModelDefinition<T>;
    parent: CoreModel;
    constructor(model: CoreModelDefinition<T>, content?: any[], parent?: CoreModel);
    add(model: ModelRefCustomProperties<T, (K & {
        uuid: string;
    }) | {
        getUuid: () => string;
    }> | ((K & {
        uuid: string;
    }) | {
        getUuid: () => string;
    })): void;
    remove(model: ModelRefCustomProperties<T, K> | string | T): void;
}
/**
 * Define 1:n relation with some sort of additional data or duplicated data
 *
 * The key of the map is the value of the FK
 */
export type ModelLinksMap<T extends CoreModel, K> = Readonly<{
    [key: string]: ModelRefCustomProperties<T, K & ({
        uuid: string;
    } | {
        getUuid: () => string;
    })>;
}> & ModelCollectionManager<K & ({
    uuid: string;
} | {
    getUuid: () => string;
})> & ModelLinker;
export declare function createModelLinksMap<T extends CoreModel>(model: CoreModelDefinition<any>, data?: any, parent?: CoreModel): {
    add: (model: ModelRefCustomProperties<T, any>) => void;
    remove: (model: ModelRefCustomProperties<T, any> | string) => void;
};
/**
 * Define the parent of the model
 */
export type ModelParent<T extends CoreModel> = ModelLink<T>;
/**
 * Define an export of actions from Model
 */
export type ModelActions = {
    [key: string]: ModelAction;
};
/**
 * Mapper attribute (target of a Mapper service)
 *
 * This is not exported as when mapped the target is always an array
 * TODO Handle 1:1 map
 */
export declare class ModelMapLoaderImplementation<T extends CoreModel, K = any> {
    protected _model: CoreModelDefinition<T>;
    protected _parent: CoreModel;
    /**
     * The uuid of the object
     */
    uuid: string;
    constructor(model: CoreModelDefinition<T>, data: {
        uuid: string;
    } & K, parent: CoreModel);
    /**
     *
     * @returns the model
     */
    get(): Promise<T>;
}
/**
 * Mapper attribute (target of a Mapper service)
 *
 * This is not exported as when mapped the target is always an array
 * TODO Handle 1:1 map
 */
export type ModelMapLoader<T extends CoreModel, K extends keyof T> = ModelMapLoaderImplementation<T, K> & Pick<T, K>;
/**
 * Define a ModelMap attribute
 *
 * K is used by the compiler to define the field it comes from
 *
 * This will instructed a ModelMapper to deduplicate information from the T model into this
 * current model attribute.
 *
 * The attribute where the current model uuid is found is defined by K
 * The attributes to dedepulicate are defined by the L type
 *
 * In the T model, the K attribute should be of type ModelLink
 */
export type ModelsMapped<T extends CoreModel, K extends FilterAttributes<T, ModelLinker>, L extends Attributes<T>> = Readonly<ModelMapLoader<T, L>[]>;
export {};
