/**
 * mongodb Helper
 *
 * @author caiaolin
 * @date 2017/5/22.
 */
import mongoose from "mongoose";

class MongooseHelper {

    /**
     * mongoose连接对象
     *
     * @var {object}
     */
    connect = null;

    /**
     * mongoose数据模型
     *
     * @var {object}
     */
    model = null;

    /**
     * 查找单一数据
     *
     * @param {object} conditions
     * @param {object} fields
     * @return {Promise}
     */
    findOne(conditions, fields = null) {
        let self = this;
        return new Promise(function (resolve, reject) {
            conditions = self._convertId(conditions);
            self.model.findOne(conditions, fields, function (error, data) {
                if (error) {
                    reject(null);
                } else {
                    resolve(data);
                }
            });
        });
    }

    /**
     * 查找数据
     *
     * @param {object} conditions
     * @param {object} fields
     * @param {object} option
     * @return {Promise}
     */
    find(conditions, fields = null, option = null) {
        let self = this;
        let limit = 0;
        let skip = 0;
        let sort = {_id:1};
        if (option !== null && Object.keys(option).length > 0) {
            limit = option.pageSize !== undefined ? option.pageSize : limit;
            skip = option.offset !== undefined ? option.offset : skip;
            sort = option.sort !== undefined ? option.sort : sort;
        }
        return new Promise(function (resolve, reject) {
            self.model.find(conditions, fields, option, function (error, data) {
                if (error) {
                    reject(error);
                } else {
                    resolve(data);
                }
            }).skip(skip).limit(limit).sort(sort);
        });
    }


    /**
     * 关联查找数据
     *
     * @param {object} conditions
     * @param {object} fields
     * @param {String|Object} populate
     * @return {Promise}
     */
    findWithPopulate(conditions, fields = null, populate = '') {
        let self = this;
        return new Promise(function (resolve, reject) {
            self.model.find(conditions, fields).populate(populate).exec(function(error, data) {
                if (error) {
                    reject(error);
                } else {
                    resolve(data);
                }
            });
        });
    }

    /**
     * 查找且更新(原子操作)
     *
     * @param {object} update
     * @param {object} condition
     * @param {object} options
     * @return {Promise}
     */
    findAndModify(condition, update, options) {
        let self = this;
        return new Promise(function (resolve, reject) {
            self.model.findOneAndUpdate(condition, update, options, function(error, data) {
                    if (error) {
                        reject(error);
                    } else {
                        resolve(data);
                    }
                });
        });
    }

    /**
     * 新增操作
     *
     * @param {object} data
     * @return {Promise}
     */
    create(data) {
        let self = this;
        return new Promise(function (resolve, reject) {
            self.model.create(data, function(error, data) {
                if (error) {
                    reject(error);
                } else {
                    resolve(data);
                }
            });
        });
    }

    /**
     * 统计数据数量
     *
     * @param {Object} condition
     * @return {Promise}
     */
    count(condition) {
        let self = this;
        return new Promise(function(resolve, reject) {
            self.model.count(condition, function(error, data) {
                if (error) {
                    reject(error);
                } else {
                    resolve(data);
                }
            });
        });
    }

    /**
     * 删除数据
     *
     * @param {Object} condition
     * @return {Promise}
     */
    delete(condition) {
        let self = this;
        return new Promise(function(resolve, reject) {
            condition = self._convertId(condition);
            self.model.remove(condition, function(error, data) {
                if (error) {
                    reject(error);
                } else {
                    resolve(data);
                }
            });
        });
    }

    /**
     * 更新数据
     *
     * @param {Object} condition
     * @param {Object} updateData
     * @return {Promise}
     */
    update(condition, updateData) {
        let self = this;
        return new Promise(function(resolve, reject) {
            condition = self._convertId(condition);
            self.model.update(condition, {$set: updateData}, function(error, data) {
                if (error) {
                    reject(error);
                } else {
                    resolve(data);
                }
            });
        });
    }

    /**
     * 自增
     *
     * @param {Object} condition
     * @param {Object} incData
     * @return {Promise}
     */
    incr(condition, incData) {
        let self = this;
        return new Promise(function(resolve, reject) {
            condition = self._convertId(condition);
            self.model.update(condition, {$inc: incData}, function(error, data) {
                if (error) {
                    reject(error);
                } else {
                    resolve(data);
                }
            });
        });
    }

    /**
     * 嵌套结构的新增
     *
     * @param {Object} condition
     * @param {Object} insertData
     * @return {Promise}
     */
    addToSet(condition, insertData) {
        let self = this;
        return new Promise(function(resolve, reject) {
            condition = self._convertId(condition);
            self.model.update(condition, {$addToSet: insertData}, function(error, data) {
                if (error) {
                    reject(error);
                } else {
                    resolve(data);
                }
            });
        });
    }

    /**
     * 删除嵌套结构数据
     *
     * @param {Object} condition
     * @param {Object} deleteData
     * @return {Promise}
     */
    deleteSet(condition, deleteData) {
        let self = this;
        return new Promise(function(resolve, reject) {
            condition = self._convertId(condition);
            self.model.update(condition, {$pull: deleteData}, function(error, data) {
                if (error) {
                    reject(error);
                } else {
                    resolve(data);
                }
            });
        });
    }


    /**
     * id转换为objectId
     *
     * @param {object} condition
     * @return {object}
     */
    _convertId(condition) {
        // 对于ID的处理
        if (condition === null || condition._id === undefined) {
            return condition;
        }
        let result = mongoose.Types.ObjectId(condition._id);
        condition._id = result;

        return condition;
    }

}

export default MongooseHelper;