import { Subscription } from 'rxjs';
import { EntityKey, ODataQueryOptions, ODataQueryOptionsHandler, ODataResource, ODataSingletonResource } from '../resources';
import { ODataEntityResource, ODataEntitySetResource, ODataNavigationPropertyResource, ODataPropertyResource } from '../resources';
import { ODataEntitySet, ODataEnumType, ODataStructuredType, ODataStructuredTypeFieldParser } from '../schema';
import { EdmType, ParserOptions } from '../types';
import { ODataCollection } from './collection';
import { ODataModel } from './model';
import { EventEmitter } from '@angular/core';
import { ODataEntitiesAnnotations, ODataEntityAnnotations } from '../annotations';
export declare enum ODataModelEventType {
    Change = "change",
    Reset = "reset",
    Update = "update",
    Sort = "sort",
    Destroy = "destroy",
    Add = "add",
    Remove = "remove",
    Invalid = "invalid",
    Request = "request",
    Sync = "sync",
    Attach = "attach"
}
export declare class ODataModelEvent<T> {
    type: ODataModelEventType | string;
    value?: any;
    previous?: any;
    options?: any;
    constructor(type: ODataModelEventType | string, { model, collection, previous, value, attr, options, bubbles, chain, }?: {
        model?: ODataModel<T>;
        collection?: ODataCollection<T, ODataModel<T>>;
        attr?: ODataModelAttribute<any> | number;
        previous?: any;
        value?: any;
        options?: any;
        bubbles?: boolean;
        chain?: [
            ODataModel<any> | ODataCollection<any, ODataModel<any>>,
            ODataModelAttribute<any> | number | null
        ][];
    });
    chain: [
        ODataModel<any> | ODataCollection<any, ODataModel<any>>,
        ODataModelAttribute<any> | number | null
    ][];
    push(model: ODataModel<any> | ODataCollection<any, ODataModel<any>>, attr: ODataModelAttribute<any> | number): ODataModelEvent<any>;
    bubbles: boolean;
    stopPropagation(): void;
    visited(model: ODataModel<any> | ODataCollection<any, ODataModel<any>>): boolean;
    canContinueWith(self: ODataModel<T> | ODataCollection<T, ODataModel<T>>): boolean;
    get path(): string;
    model?: ODataModel<T>;
    get currentModel(): ODataModel<any> | undefined;
    collection?: ODataCollection<T, ODataModel<T>>;
    get currentCollection(): ODataCollection<any, ODataModel<any>> | undefined;
}
export declare class ODataModelEventEmitter<T> extends EventEmitter<ODataModelEvent<T>> {
    model?: ODataModel<T>;
    collection?: ODataCollection<T, ODataModel<T>>;
    constructor({ model, collection, }?: {
        model?: ODataModel<T>;
        collection?: ODataCollection<T, ODataModel<T>>;
    });
    trigger(type: ODataModelEventType | string, { collection, previous, value, attr, options, bubbles, }?: {
        collection?: ODataCollection<T, ODataModel<T>>;
        attr?: ODataModelAttribute<any> | number;
        previous?: any;
        value?: any;
        options?: any;
        bubbles?: boolean;
    }): void;
}
export declare const BUBBLES: (ODataModelEventType | string)[];
export declare const INCLUDE_SHALLOW: {
    include_concurrency: boolean;
    include_computed: boolean;
    include_key: boolean;
    include_id: boolean;
};
export declare const INCLUDE_DEEP: {
    include_concurrency: boolean;
    include_computed: boolean;
    include_key: boolean;
    include_id: boolean;
    include_navigation: boolean;
    include_non_field: boolean;
};
export declare enum ODataModelState {
    Added = 0,
    Removed = 1,
    Changed = 2,
    Unchanged = 3
}
export type ModelInterface<T> = {
    [P in keyof T]: T[P] extends (infer U)[] ? ODataCollection<U, ODataModel<U> & ModelInterface<U>> : T[P] extends object ? ODataModel<T[P]> & ModelInterface<T[P]> : T[P];
};
export type ModelOptions = {
    cid?: string;
    fields: Map<string, ModelFieldOptions>;
};
export type ModelFieldOptions = {
    field?: string;
    parser?: ODataStructuredTypeFieldParser<any>;
    default?: any;
    required?: boolean;
    concurrency?: boolean;
    maxLength?: number;
    minLength?: number;
    min?: number;
    max?: number;
    pattern?: RegExp;
};
export declare function Model({ cid }?: {
    cid?: string;
}): <T extends {
    new (...args: any[]): {};
}>(constructor: T) => T;
export declare function ModelField({ name, ...options }?: {
    name?: string;
} & ModelFieldOptions): (target: any, key: string) => void;
export type ODataModelFieldOptions<F> = ModelFieldOptions & {
    name: string;
    field: string;
    parser: ODataStructuredTypeFieldParser<F>;
};
export declare class ODataModelField<F> {
    name: string;
    field: string;
    parser: ODataStructuredTypeFieldParser<F>;
    options: ODataModelOptions<any>;
    optionsForType?: (type: string) => ODataModelOptions<any> | undefined;
    modelForType?: (t: string) => typeof ODataModel<any> | undefined;
    collectionForType?: (t: string) => typeof ODataCollection<any, ODataModel<any>> | undefined;
    enumForType?: (t: string) => ODataEnumType<F> | undefined;
    structuredForType?: (t: string) => ODataStructuredType<F> | undefined;
    default?: any;
    required: boolean;
    concurrency: boolean;
    maxLength?: number;
    minLength?: number;
    min?: number;
    max?: number;
    pattern?: RegExp;
    parserOptions?: ParserOptions;
    constructor(options: ODataModelOptions<any>, { name, field, parser, ...opts }: ODataModelFieldOptions<F>);
    get type(): string;
    get navigation(): boolean;
    get collection(): boolean;
    annotatedValue<T>(term: string | RegExp): T | undefined;
    configure({ optionsForType, modelForType, collectionForType, enumForType, structuredForType, concurrency, options, }: {
        optionsForType: (type: string) => ODataModelOptions<any> | undefined;
        modelForType: (t: string) => typeof ODataModel<any> | undefined;
        collectionForType: (t: string) => typeof ODataCollection<any, any> | undefined;
        enumForType: (t: string) => ODataEnumType<any> | undefined;
        structuredForType: (t: string) => ODataStructuredType<any> | undefined;
        concurrency: boolean;
        options: ParserOptions;
    }): void;
    isKey(): boolean;
    hasReferentials(): boolean;
    get referentials(): import("../schema").ODataReferential[];
    isStructuredType(): boolean;
    structuredType(): ODataStructuredType<F>;
    isEnumType(): boolean;
    enumType(): ODataEnumType<F>;
    validate(value: any, { method, navigation, }?: {
        method?: 'create' | 'update' | 'modify';
        navigation?: boolean;
    }): any;
    defaults(): any;
    deserialize(value: any, options?: ParserOptions): F;
    serialize(value: F, options?: ParserOptions): any;
    encode(value: F, options?: ParserOptions): any;
    resourceFactory<T, F>(base: ODataResource<T>): ODataNavigationPropertyResource<F> | ODataPropertyResource<F>;
    annotationsFactory<T, F>(base: ODataEntityAnnotations<T>): ODataEntityAnnotations<F> | ODataEntitiesAnnotations<F>;
    modelFactory<F>({ parent, value, reset, }: {
        parent: ODataModel<any>;
        value?: Partial<F> | {
            [name: string]: any;
        };
        reset?: boolean;
    }): ODataModel<F>;
    collectionFactory<F>({ parent, value, reset, }: {
        parent: ODataModel<any>;
        value?: Partial<F>[] | {
            [name: string]: any;
        }[];
        reset?: boolean;
    }): ODataCollection<F, ODataModel<F>>;
}
export declare class ODataModelAttribute<T> {
    private _model;
    private _field;
    private state;
    private value?;
    private change?;
    private subscription?;
    events$: ODataModelEventEmitter<T>;
    constructor(_model: ODataModel<any>, _field: ODataModelField<T>);
    get type(): string;
    get navigation(): boolean;
    get computed(): boolean | undefined;
    get concurrency(): boolean;
    get referentials(): import("../schema").ODataReferential[];
    get options(): ODataModelOptions<any>;
    get name(): string;
    get fieldName(): string;
    get(): T | ODataModel<T> | ODataCollection<T, ODataModel<T>> | null | undefined;
    set(value: T | ODataModel<T> | ODataCollection<T, ODataModel<T>> | null | undefined, reset?: boolean, reparent?: boolean): boolean;
    isChanged({ include_navigation, }?: {
        include_navigation?: boolean;
    }): boolean;
    reset(): void;
    private link;
    private unlink;
}
export type ODataModelEntry<T, M extends ODataModel<T>> = {
    state: ODataModelState;
    model: M;
    key?: EntityKey<T> | {
        [name: string]: any;
    };
    subscription?: Subscription;
};
export declare class ODataModelOptions<T> {
    name: string;
    cid: string;
    base?: string;
    private _fields;
    structuredType: ODataStructuredType<T>;
    entitySet?: ODataEntitySet;
    parent?: ODataModelOptions<any>;
    children: ODataModelOptions<any>[];
    events$: ODataModelEventEmitter<T>;
    constructor({ config, structuredType, }: {
        config: ModelOptions;
        structuredType: ODataStructuredType<T>;
    });
    get api(): import("angular-odata").ODataApi;
    type({ alias }?: {
        alias?: boolean;
    }): string;
    isOpenType(): boolean;
    isEntityType(): boolean;
    isComplexType(): boolean;
    isTypeOf(type: string): boolean;
    isModelFor(entity: T | {
        [name: string]: any;
    }): boolean;
    findChildOptions(predicate: (options: ODataModelOptions<any>) => boolean): ODataModelOptions<any> | undefined;
    configure({ options }: {
        options: ParserOptions;
    }): void;
    fields({ include_navigation, include_parents, }: {
        include_parents: boolean;
        include_navigation: boolean;
    }): ODataModelField<any>[];
    field<F>(name: keyof T | string): ODataModelField<F>;
    findField<F>(name: keyof T | string, { reset }?: {
        reset?: boolean;
    }): ODataModelField<F> | undefined;
    addField<F>(name: string, options: ModelFieldOptions): ODataModelField<F>;
    tsToEdm: Record<string, EdmType>;
    private modelFieldFactory;
    attach(self: ODataModel<T>, resource: ODataEntityResource<T> | ODataNavigationPropertyResource<T> | ODataPropertyResource<T> | ODataSingletonResource<T>): void;
    static chain(child: ODataModel<any> | ODataCollection<any, ODataModel<any>>): [
        ODataModel<any> | ODataCollection<any, ODataModel<any>>,
        ODataModelField<any> | null
    ][];
    static resource<T>(child: ODataModel<T> | ODataCollection<T, ODataModel<T>>): ODataResource<T> | null;
    collectionResourceFactory(query?: ODataQueryOptions<T>): ODataEntitySetResource<T> | ODataNavigationPropertyResource<T> | ODataPropertyResource<T> | null;
    modelResourceFactory(query?: ODataQueryOptions<T>): ODataEntityResource<T> | ODataNavigationPropertyResource<T> | ODataPropertyResource<T> | ODataSingletonResource<T> | null;
    bind(self: ODataModel<T>, { parent, resource, annots, }?: {
        parent?: [
            ODataModel<any> | ODataCollection<any, ODataModel<any>>,
            ODataModelField<any> | null
        ];
        resource?: ODataResource<T> | null;
        annots?: ODataEntityAnnotations<T>;
    }): void;
    query(self: ODataModel<T>, resource: ODataEntityResource<T> | ODataPropertyResource<T> | ODataNavigationPropertyResource<T> | ODataSingletonResource<T>, func: (q: ODataQueryOptionsHandler<T>, s?: ODataStructuredType<T>) => void): ODataModel<T>;
    resolveKey(value: ODataModel<T> | T | {
        [name: string]: any;
    }, { field_mapping, resolve, single, }?: {
        field_mapping?: boolean;
        resolve?: boolean;
        single?: boolean;
    }): EntityKey<T> | {
        [name: string]: any;
    } | undefined;
    resolveReferential(value: ODataModel<T> | T | {
        [name: string]: any;
    } | null, attr: ODataModelAttribute<any> | ODataModelField<any>, { field_mapping, resolve, single, }?: {
        field_mapping?: boolean;
        resolve?: boolean;
        single?: boolean;
    }): {
        [name: string]: any;
    } | null | undefined;
    resolveReferenced(value: ODataModel<T> | T | {
        [name: string]: any;
    } | null, attr: ODataModelAttribute<any> | ODataModelField<any>, { field_mapping, resolve, single, }?: {
        field_mapping?: boolean;
        resolve?: boolean;
        single?: boolean;
    }): {
        [name: string]: any;
    } | null | undefined;
    validate(self: ODataModel<T>, { method, navigation, }?: {
        method?: 'create' | 'update' | 'modify';
        navigation?: boolean;
    }): {
        [name: string]: string[];
    } | undefined;
    defaults(): T | {
        [name: string]: any;
    } | undefined;
    hasChanged(self: ODataModel<T>, { include_navigation }?: {
        include_navigation?: boolean;
    }): boolean;
    hasKey(self: ODataModel<T>): boolean;
    withResource<R, M extends ODataModel<T>>(self: M, resource: ODataEntityResource<T> | ODataPropertyResource<T> | ODataNavigationPropertyResource<T> | ODataSingletonResource<T> | null, ctx: (model: M) => R): R;
    asEntity<R, M extends ODataModel<T>>(self: M, ctx: (model: M) => R): R;
    toEntity(self: ODataModel<T>, { client_id, include_navigation, include_concurrency, include_computed, include_key, include_id, include_non_field, changes_only, field_mapping, chain, }?: {
        client_id?: boolean;
        include_navigation?: boolean;
        include_concurrency?: boolean;
        include_computed?: boolean;
        include_key?: boolean;
        include_id?: boolean;
        include_non_field?: boolean;
        changes_only?: boolean;
        field_mapping?: boolean;
        chain?: (ODataModel<any> | ODataCollection<any, ODataModel<any>>)[];
    }): T | {
        [name: string]: any;
    };
    reset(self: ODataModel<T>, { name, silent }?: {
        name?: string;
        silent?: boolean;
    }): void;
    assign(self: ODataModel<T>, entity: Partial<T> | {
        [name: string]: any;
    }, { add, merge, remove, reset, reparent, silent, }?: {
        add?: boolean;
        merge?: boolean;
        remove?: boolean;
        reset?: boolean;
        reparent?: boolean;
        silent?: boolean;
    }): ODataModel<T>;
    static isModel(obj: any): boolean;
    static isCollection(obj: any): boolean;
    get<F>(self: ODataModel<T>, field: ODataModelField<F> | string): F | ODataModel<F> | ODataCollection<F, ODataModel<F>> | null | undefined;
    set<F>(self: ODataModel<T>, field: ODataModelField<F> | string, value: F | F[] | {
        [name: string]: any;
    } | {
        [name: string]: any;
    }[] | ODataModel<F> | ODataCollection<F, ODataModel<F>> | null, { add, merge, remove, reset, reparent, silent, type, }?: {
        add?: boolean;
        merge?: boolean;
        remove?: boolean;
        reset?: boolean;
        reparent?: boolean;
        silent?: boolean;
        type?: EdmType | string;
    }): boolean;
    private _link;
}
