import { ObjectLiteral } from '../common/ObjectLiteral';
import { Brackets } from './Brackets';

/**
 * Query Builders can implement this interface to support where expression
 */
export interface WhereExpressionBuilder {
	/**
	 * Sets WHERE condition in the query builder.
	 * If you had previously WHERE expression defined,
	 * calling this function will override previously set WHERE conditions.
	 * Additionally you can add parameters used in where expression.
	 */
	where(where: string, parameters?: ObjectLiteral): this;

	/**
	 * Sets WHERE condition in the query builder.
	 * If you had previously WHERE expression defined,
	 * calling this function will override previously set WHERE conditions.
	 * Additionally you can add parameters used in where expression.
	 */
	where(where: Brackets, parameters?: ObjectLiteral): this;

	/**
	 * Sets WHERE condition in the query builder.
	 * If you had previously WHERE expression defined,
	 * calling this function will override previously set WHERE conditions.
	 * Additionally you can add parameters used in where expression.
	 */
	where(where: ObjectLiteral, parameters?: ObjectLiteral): this;

	/**
	 * Sets WHERE condition in the query builder.
	 * If you had previously WHERE expression defined,
	 * calling this function will override previously set WHERE conditions.
	 * Additionally you can add parameters used in where expression.
	 */
	where(where: ObjectLiteral[], parameters?: ObjectLiteral): this;

	/**
	 * Sets WHERE condition in the query builder.
	 * If you had previously WHERE expression defined,
	 * calling this function will override previously set WHERE conditions.
	 * Additionally you can add parameters used in where expression.
	 */
	where(subQuery: (qb: this) => string, parameters?: ObjectLiteral): this;

	/**
	 * Adds new AND WHERE condition in the query builder.
	 * Additionally you can add parameters used in where expression.
	 */
	andWhere(where: string, parameters?: ObjectLiteral): this;

	/**
	 * Adds new AND WHERE condition in the query builder.
	 * Additionally you can add parameters used in where expression.
	 */
	andWhere(where: Brackets, parameters?: ObjectLiteral): this;

	/**
	 * Adds new AND WHERE condition in the query builder.
	 * Additionally you can add parameters used in where expression.
	 */
	andWhere(where: ObjectLiteral, parameters?: ObjectLiteral): this;

	/**
	 * Adds new AND WHERE condition in the query builder.
	 * Additionally you can add parameters used in where expression.
	 */
	andWhere(where: ObjectLiteral[], parameters?: ObjectLiteral): this;

	/**
	 * Adds new AND WHERE condition in the query builder.
	 * Additionally you can add parameters used in where expression.
	 */
	andWhere(subQuery: (qb: this) => string, parameters?: ObjectLiteral): this;

	/**
	 * Adds new OR WHERE condition in the query builder.
	 * Additionally you can add parameters used in where expression.
	 */
	orWhere(where: string, parameters?: ObjectLiteral): this;

	/**
	 * Adds new OR WHERE condition in the query builder.
	 * Additionally you can add parameters used in where expression.
	 */
	orWhere(where: Brackets, parameters?: ObjectLiteral): this;

	/**
	 * Adds new OR WHERE condition in the query builder.
	 * Additionally you can add parameters used in where expression.
	 */
	orWhere(where: ObjectLiteral, parameters?: ObjectLiteral): this;

	/**
	 * Adds new OR WHERE condition in the query builder.
	 * Additionally you can add parameters used in where expression.
	 */
	orWhere(where: ObjectLiteral[], parameters?: ObjectLiteral): this;

	/**
	 * Adds new OR WHERE condition in the query builder.
	 * Additionally you can add parameters used in where expression.
	 */
	orWhere(subQuery: (qb: this) => string, parameters?: ObjectLiteral): this;

	/**
	 * Sets WHERE condition in the query builder with a condition for the given ids.
	 * If you had previously WHERE expression defined,
	 * calling this function will override previously set WHERE conditions.
	 *
	 * Ids are mixed.
	 * It means if you have single primary key you can pass a simple id values, for example [1, 2, 3].
	 * If you have multiple primary keys you need to pass object with property names and values specified,
	 * for example [{ firstId: 1, secondId: 2 }, { firstId: 2, secondId: 3 }, ...]
	 */
	whereInIds(ids: any | any[]): this;

	/**
	 * Adds new AND WHERE with conditions for the given ids.
	 *
	 * Ids are mixed.
	 * It means if you have single primary key you can pass a simple id values, for example [1, 2, 3].
	 * If you have multiple primary keys you need to pass object with property names and values specified,
	 * for example [{ firstId: 1, secondId: 2 }, { firstId: 2, secondId: 3 }, ...]
	 */
	andWhereInIds(ids: any | any[]): this;

	/**
	 * Adds new OR WHERE with conditions for the given ids.
	 *
	 * Ids are mixed.
	 * It means if you have single primary key you can pass a simple id values, for example [1, 2, 3].
	 * If you have multiple primary keys you need to pass object with property names and values specified,
	 * for example [{ firstId: 1, secondId: 2 }, { firstId: 2, secondId: 3 }, ...]
	 */
	orWhereInIds(ids: any | any[]): this;
}

/**
 * @deprecated Use `WhereExpressionBuilder` instead
 */
export interface WhereExpression extends WhereExpressionBuilder {}
