"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("../../../utils");
class Where {
    constructor(namedTable, needWhere = true) {
        this.tokens = [];
        this.params = [];
        this._notNull = false;
        this._notBlank = false;
        this.namedTable = namedTable;
        this.needWhere = needWhere;
    }
    /**
     * 克隆
     */
    clone() {
        const where = new Where(this.namedTable, this.needWhere);
        where.tokens.push(...this.tokens);
        where.params.push(...this.params);
        where.notNull = this.notNull;
        where.notBlank = this.notBlank;
        return where;
    }
    /**
     * 过滤`null`的参数
     */
    notNull(flag = true) {
        this._notNull = flag;
        return this;
    }
    /**
     * 过滤`blank`的参数
     */
    notBlank(flag = true) {
        this._notBlank = flag;
        return this;
    }
    /**
     * 等于`=`,如：`eq('name', '老王') ---> name = '老王'`
     * @param condition 判断表达式，当为true时拼接条件
     * @param column 数据库中的列名
     * @param value 值
     */
    eq(condition, column, value) {
        if (arguments.length == 2) {
            value = column;
            column = condition;
            condition = true;
        }
        if (condition && this.filterNullAndBlank(value)) {
            // tokens.add(namedTable.rowMapColumnMapper.apply(column));
            this.tokens.push(column);
            if (value == null) {
                this.append(' is null');
            }
            else {
                this.params.push(value);
                this.append(' = ?');
            }
            this.appendAnd();
        }
        return this;
    }
    /**
     * 不等于`<>`,如：`ne('name', '老王') ---> name <> '老王'`
     * @param condition 判断表达式，当为true时拼接条件
     * @param column 数据库中的列名
     * @param value 值
     */
    ne(condition, column, value) {
        if (arguments.length == 2) {
            value = column;
            column = condition;
            condition = true;
        }
        if (condition && this.filterNullAndBlank(value)) {
            // tokens.add(namedTable.rowMapColumnMapper.apply(column));
            this.tokens.push(column);
            if (value == null) {
                this.append('is not null');
            }
            else {
                this.params.push(value);
                this.append('<> ?');
            }
            this.appendAnd();
        }
        return this;
    }
    /**
     * 小于`<`,如：`lt('age', 18) ---> age < 18
     * @param condition 判断表达式，当为true时拼接条件
     * @param column 数据库中的列名
     * @param value 值
     */
    lt(condition, column, value) {
        if (arguments.length == 2) {
            value = column;
            column = condition;
            condition = true;
        }
        return this.append(condition, column, ' < ?', value);
    }
    /**
     * 小于等于`<=`,如：`lte('age', 18) ---> age <= 18
     * @param condition 判断表达式，当为true时拼接条件
     * @param column 数据库中的列名
     * @param value 值
     */
    lte(condition, column, value) {
        if (arguments.length == 2) {
            value = column;
            column = condition;
            condition = true;
        }
        return this.append(condition, column, ' <= ?', value);
    }
    /**
     * 大于`>`,如：`gt('age', 18) ---> age > 18
     * @param condition 判断表达式，当为true时拼接条件
     * @param column 数据库中的列名
     * @param value 值
     */
    gt(condition, column, value) {
        if (arguments.length == 2) {
            value = column;
            column = condition;
            condition = true;
        }
        return this.append(condition, column, ' > ?', value);
    }
    /**
     * 大于等于`>=`,如：`gte('age', 18) ---> age >= 18
     * @param condition 判断表达式，当为true时拼接条件
     * @param column 数据库中的列名
     * @param value 值
     */
    gte(condition, column, value) {
        if (arguments.length == 2) {
            value = column;
            column = condition;
            condition = true;
        }
        return this.append(condition, column, ' >= ?', value);
    }
    /**
     * `in`,如：`in('age', [1,2,3]) ---> age in (1,2,3)
     * @param condition 判断表达式，当为true时拼接条件
     * @param column 数据库中的列名
     * @param value 值
     */
    in(condition, column, value) {
        if (arguments.length == 2) {
            value = column;
            column = condition;
            condition = true;
        }
        if (condition && value != null) {
            const objects = value;
            if (objects.length > 0) {
                // append(namedTable.rowMapColumnMapper.apply(column));
                this.append(column);
                this.append(' in (');
                // this.append(String.join(',', Collections.nCopies(objects.size(), '?')));
                this.append(Array.from({ length: objects.length })
                    .map(() => '?')
                    .join(','));
                this.append(')');
                this.appendAnd();
                this.params.push(...objects);
            }
        }
        return this;
    }
    /**
     * `not in`,如：`notIn('age', [1,2,3]) ---> age not in (1,2,3)
     * @param condition 判断表达式，当为true时拼接条件
     * @param column 数据库中的列名
     * @param value 值
     */
    notIn(condition, column, value) {
        if (arguments.length == 2) {
            value = column;
            column = condition;
            condition = true;
        }
        if (condition && value != null) {
            const objects = value;
            if (objects.length > 0) {
                // append(namedTable.rowMapColumnMapper.apply(column));
                this.append(column);
                this.append('not in (');
                // this.append(String.join(',', Collections.nCopies(objects.size(), '?')));
                this.append(Array.from({ length: objects.length })
                    .map(() => '?')
                    .join(','));
                this.append(')');
                this.appendAnd();
                this.params.push(...objects);
            }
        }
        return this;
    }
    /**
     * `like`,如：`like('name', '%王%') ---> name like '%王%'
     * @param condition 判断表达式，当为true时拼接条件
     * @param column 数据库中的列名
     * @param value 值
     */
    like(condition, column, value) {
        if (arguments.length == 2) {
            value = column;
            column = condition;
            condition = true;
        }
        return this.append(condition, column, 'like ?', value);
    }
    /**
     * not like`,如：`notLike('name', '%王%') ---> name not like '%王%'
     * @param condition 判断表达式，当为true时拼接条件
     * @param column 数据库中的列名
     * @param value 值
     */
    notLike(condition, column, value) {
        if (arguments.length == 2) {
            value = column;
            column = condition;
            condition = true;
        }
        return this.append(condition, column, 'not like ?', value);
    }
    /**
     * `is null`,如：`isNull('name') ---> name is null
     * @param condition 判断表达式，当为true时拼接条件
     * @param column 数据库中的列名
     */
    isNull(condition, column) {
        if (arguments.length == 1) {
            column = condition;
            condition = true;
        }
        if (condition) {
            // this.append(namedTable.rowMapColumnMapper.apply(column));
            this.append(column);
            this.append('is null');
            this.appendAnd();
        }
        return this;
    }
    /**
     * `is not null`,如：`isNotNull('name') ---> name is not null
     * @param condition 判断表达式，当为true时拼接条件
     * @param column 数据库中的列名
     */
    isNotNull(condition, column) {
        if (arguments.length == 1) {
            column = condition;
            condition = true;
        }
        if (condition) {
            // this.append(namedTable.rowMapColumnMapper.apply(column));
            this.append(column);
            this.append('is not null');
            this.appendAnd();
        }
        return this;
    }
    /**
     * 拼接`or`
     */
    or() {
        this.appendOr();
        return this;
    }
    /**
     * 拼接`and`
     * `and`嵌套，如and(it => it.eq('name','李白').ne('status','正常') --> and (name = '李白' and status <> '正常')
     * @param condition 判断表达式，当为true时拼接条件
     * @param _function 回调函数
     */
    and(condition, _function) {
        if (arguments.length === 0) {
            this.appendAnd();
            return this;
        }
        else if (arguments.length === 1) {
            _function = condition;
            condition = true;
        }
        if (condition) {
            const expr = _function(new Where(this.namedTable, false));
            this.params.push(...expr.params);
            this.append('(');
            this.append(expr.getSql());
            this.append(')');
            this.appendAnd();
        }
        return this;
    }
    /**
     * 拼接`order by xxx asc/desc`
     * @param column 要排序的列
     * @param sort `asc`或`desc`
     */
    orderBy(column, sort = 'asc') {
        this.namedTable.orderBy(column, sort);
        return this;
    }
    /**
     * 拼接拼接`order by xxx desc`
     * @param column 要排序的列
     */
    orderByDesc(column) {
        return this.orderBy(column, 'desc');
    }
    /**
     * 拼接`group by`
     * @param columns 要分组的列
     */
    groupBy(...columns) {
        this.namedTable.groupBy(...columns);
        return this;
    }
    /**
     * 保存到表中，当主键有值时则修改，否则插入
     * @param data 各项列和值
     * @param beforeQuery 是否根据id查询有没有数据
     */
    save(data, beforeQuery = false) {
        return this.namedTable.save(data);
    }
    /**
     * 执行插入语句，返回主键
     * @param data 各项列和值
     */
    insert(data) {
        return this.namedTable.insert(data);
    }
    /**
     * 执行delete语句
     */
    delete() {
        return this.namedTable.delete();
    }
    /**
     * 执行update语句
     * @param data 各项列和值
     * @param isUpdateBlank 是否更新空值字段
     */
    update(data, isUpdateBlank) {
        return this.namedTable.update(data);
    }
    /**
     * 执行分页查询，分页条件手动传入
     * @param limit 限制条数
     * @param offset 跳过条数
     */
    page(limit, offset) {
        return this.namedTable.page(limit, offset);
    }
    /**
     * 执行select查询
     */
    select() {
        return this.namedTable.select();
    }
    /**
     * 执行selectOne查询
     */
    selectOne() {
        return this.namedTable.selectOne();
    }
    /**
     * 查询条数
     */
    count() {
        return this.namedTable.count();
    }
    /**
     * 查询是否存在
     */
    exists() {
        return this.namedTable.exists();
    }
    appendAnd() {
        this.remove();
        this.tokens.push('and');
    }
    appendOr() {
        this.remove();
        this.tokens.push('or');
    }
    remove() {
        let size = this.tokens.length;
        while (size > 0) {
            const token = this.tokens[size - 1];
            const lowerCase = token.toLowerCase();
            if ('and' === lowerCase || 'or' === lowerCase) {
                this.tokens.splice(size - 1, 1);
                size--;
            }
            else {
                break;
            }
        }
        while (size > 0) {
            const token = this.tokens[0];
            const lowerCase = token.toLowerCase();
            if ('and' === lowerCase || 'or' === lowerCase) {
                this.tokens.splice(0, 1);
                size--;
            }
            else {
                break;
            }
        }
    }
    isEmpty() {
        return this.tokens.length === 0;
    }
    getSql() {
        this.remove();
        if (this.isEmpty()) {
            return '';
        }
        return (this.needWhere ? ' where ' : '') + this.tokens.join(' ');
    }
    filterNullAndBlank(value) {
        if (this._notNull && value == null) {
            return false;
        }
        return !this._notBlank || !(0, utils_1.isEmpty)(value.toString() || '');
    }
    append(append, column, condition, value) {
        if (arguments.length == 1) {
            this.tokens.push(append);
        }
        else if (arguments.length == 2) {
            this.tokens.push(append);
            this.params.push(column);
        }
        else {
            if (append && this.filterNullAndBlank(value)) {
                // this.append(this.namedTable.rowMapColumnMapper.apply(column));
                this.append(column);
                this.append(condition);
                this.appendAnd();
                this.params.push(value);
            }
        }
        return this;
    }
}
exports.default = Where;
//# sourceMappingURL=Where.js.map