/**
 * Used to specify what entity relations should be loaded.
 *
 * Example:
 *  const options: JoinOptions = {
 *     alias: "photo",
 *     leftJoin: {
 *         author: "photo.author",
 *         categories: "categories",
 *         user: "categories.user",
 *         profile: "user.profile"
 *     },
 *     innerJoin: {
 *         author: "photo.author",
 *         categories: "categories",
 *         user: "categories.user",
 *         profile: "user.profile"
 *     },
 *     leftJoinAndSelect: {
 *         author: "photo.author",
 *         categories: "categories",
 *         user: "categories.user",
 *         profile: "user.profile"
 *     },
 *     innerJoinAndSelect: {
 *         author: "photo.author",
 *         categories: "categories",
 *         user: "categories.user",
 *         profile: "user.profile"
 *     }
 * };
 */
export interface JoinOptions {
    /**
     * Alias of the main entity.
     */
    alias: string;
    /**
     * Array of columns to LEFT JOIN.
     */
    leftJoinAndSelect?: {
        [key: string]: string;
    };
    /**
     * Array of columns to INNER JOIN.
     */
    innerJoinAndSelect?: {
        [key: string]: string;
    };
    /**
     * Array of columns to LEFT JOIN.
     */
    leftJoin?: {
        [key: string]: string;
    };
    /**
     * Array of columns to INNER JOIN.
     */
    innerJoin?: {
        [key: string]: string;
    };
}

/**
 * Interface of the simple literal object with any string keys.
 */
export interface ObjectLiteral {
    [key: string]: any;
}

/**
 * Used for find operations.
 */
export declare type FindConditions<T> = {
    [P in keyof T]?: T[P] extends never ? FindConditions<T[P]>
        : FindConditions<T[P]>;
};

// import { ObjectLiteral } from "../common/ObjectLiteral";
// import { FindConditions } from "./FindConditions";
/**
 * Defines a special criteria to find specific entity.
 */
export interface FindOneOptions<Entity = any> {
    /**
     * Specifies what columns should be retrieved.
     */
    select?: any[];
    /**
     * Simple condition that should be applied to match entities.
     */
    where?: FindConditions<Entity>[] | FindConditions<Entity> | ObjectLiteral | string;
    /**
     * Indicates what relations of entity should be loaded (simplified left join form).
     */
    relations?: any[];

    // 暂不支持join，有待进一步检查实现方案。
    // /**
    //  * Specifies what relations should be loaded.
    //  */
    join?: JoinOptions;

    /**
     * Order, in which entities should be ordered.
     */
    order?: {
        [P in keyof Entity]?: 'ASC' | 'DESC' | 1 | -1;
    };
    /**
     * Enables or disables query result caching.
     */
    cache?: boolean | number | {
        id: any;
        milliseconds: number;
    };
    /**
     * Enables or disables query result caching.
     */
    lock?: {
        mode: 'optimistic';
        version: number;
        // version: number | Date;
    } | {
        mode: 'pessimistic_read' | 'pessimistic_write';
        // mode: 'pessimistic_read' | 'pessimistic_write' | 'dirty_read';
    };
    // /**
    //  * If sets to true then loads all relation ids of the entity and maps them into relation values (not relation objects).
    //  * If array of strings is given then loads only relation ids of the given properties.
    //  */
    // loadRelationIds?: boolean | {
    //     relations?: string[];
    //     disableMixedMap?: boolean;
    // };
    // /**
    //  * Indicates if eager relations should be loaded or not.
    //  * By default they are loaded when find methods are used.
    //  */
    // loadEagerRelations?: boolean;
}

/**
 * Defines a special criteria to find specific entities.
 */
export interface FindManyOptions<Entity = any> extends FindOneOptions<Entity> {
    /**
     * Offset (paginated) where from entities should be taken.
     */
    skip?: number;
    /**
     * Limit (paginated) - max number of entities should be taken.
     */
    take?: number;
}
