"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
Object.defineProperty(exports, "__esModule", { value: true });
var _ = require("lodash");
var React = require("react");
var Ajax_1 = require("./Ajax");
var antd_1 = require("antd");
/**
 * 更新一个列表中的一个对象，并返回一个新的列表
 * @param list 需要被修改的列表
 * @param data 新的数据
 * @param rowKey 列表中数据的主键，如果不传，则为 `id`
 * @return 一个新的列表
*/
function update(list, data, rowKey) {
    if (rowKey === void 0) { rowKey = 'id'; }
    var tmp = _.concat([], list);
    tmp.map(function (item) { return _.unset(item, '__EFFECT'); });
    var param = {};
    param[rowKey] = data[rowKey];
    var index = _.findIndex(tmp, param);
    if (index >= 0) {
        var obj = _.assign({}, data);
        obj.__EFFECT = obj.__EFFECT == 'on' ? 'reon' : 'on';
        tmp[index] = obj;
    }
    return tmp;
}
/**
 * 往列表的最前面插入一项，并返回一个新的列表
 * @param list 需要被插入的列表
 * @param data 新的数据
*/
function add(list, data, rowKey) {
    if (rowKey === void 0) { rowKey = 'id'; }
    var tmp = _.concat([], list);
    var obj = _.assign({}, data);
    tmp.map(function (item) { return _.unset(item, '__EFFECT'); });
    if (!_.has(data, rowKey)) {
        obj.__NEW = true;
    }
    obj.__EFFECT = 'on';
    tmp.unshift(obj);
    return tmp;
}
/**
 * 在一个列表里面删除指定的数据，并返回一个新的列表
 * @param list 需要被插入的列表
 * @param ids 需要删除的 id 列表
 * @param rowKey 每条数据的识别的主键 默认为 'id'
*/
function del(list, ids, rowKey) {
    if (rowKey === void 0) { rowKey = 'id'; }
    _.map(ids, function (id, i) { return ids[i] = id + ''; });
    return _.filter(list, function (item) {
        return _.indexOf(ids, (item[rowKey] + '')) == -1;
    });
}
function doLoad(state, data) {
    var param = {};
    _.keys(data).map(function (key) { if (key != 'type') {
        param[key] = data[key];
    } });
    return __assign({}, state, param);
}
/**
 * 构建一个脐具备增删改查功能的 Model.
 * 构造出的Model 具备  _query,_add,_update,_delete 四个属性
 * _query : ({query})    _query  必须传入一个 query 表示查询条件
 * _add : ({data})       _add    必须传入一个 data 表示新增对象
 * _update: ({data})     _update 必须传一个 data 表示修改对象
 * _delete: ({data})     _delete 时，传入的data 可以是一个对象(以rowKey为ID)，也可以是一个ID的数组
 *                          另外说明，_delete 请求以 ids 为参数，多条记录删除时，以逗号分隔
 *
 * @param modelName dva 模块名字，不能重复
 * @param api 参考上文说明
 * @param objectName 对象的名字 默认为 '对象'
 * @param rowKey 每条数据的识别的主键 默认为 'id'
 * @param nameField 每条数据的名称字段 默认为空
 * @param pre 预处理的方法，如果定义的话，会预先执行此方法进行数据转换
 *
*/
function BuildModel(modelName, api, objectName, rowKey, nameField, pre) {
    if (objectName === void 0) { objectName = '对象'; }
    if (rowKey === void 0) { rowKey = 'id'; }
    if (nameField === void 0) { nameField = null; }
    if (pre === void 0) { pre = null; }
    var tip = function (data) { return React.createElement("span", null,
        objectName,
        " ",
        nameField ? React.createElement("strong", null, data[nameField]) : React.createElement(React.Fragment, null),
        " "); };
    var _LastQuery = {};
    var apis = { query: '' };
    if (_.isString(api)) {
        apis = {
            query: api,
            add: api,
            del: api,
            update: api,
        };
    }
    else {
        apis = api;
    }
    var model = {
        //命名空间，不能重复
        namespace: modelName,
        //如果需要使用 TableLayout 进行快速管理，则必须包含 list, 和 total 两个状态
        state: {
            list: [],
            total: 0,
            _current: 1,
        },
        effects: {
            // 刷新列表
            _reflush: function (_a, _b) {
                var resp, e_1;
                var put = _b.put;
                return __generator(this, function (_c) {
                    switch (_c.label) {
                        case 0:
                            _.assign(_LastQuery, { start_: 0 });
                            _c.label = 1;
                        case 1:
                            _c.trys.push([1, 5, , 6]);
                            return [4 /*yield*/, Ajax_1.default.POST(apis.query, _LastQuery)];
                        case 2:
                            resp = _c.sent();
                            if (!(resp.code === null || resp.code == '0')) return [3 /*break*/, 4];
                            return [4 /*yield*/, put({
                                    type: '_list',
                                    list: resp.list,
                                    total: resp.total
                                })];
                        case 3:
                            _c.sent();
                            _c.label = 4;
                        case 4: return [3 /*break*/, 6];
                        case 5:
                            e_1 = _c.sent();
                            return [3 /*break*/, 6];
                        case 6: return [2 /*return*/];
                    }
                });
            },
            // 查询列表
            _query: function (_a, _b) {
                var _current, resp, e_2;
                var query = _a.query, extraQuery = _a.extraQuery, callback = _a.callback;
                var put = _b.put;
                return __generator(this, function (_c) {
                    switch (_c.label) {
                        case 0:
                            if (extraQuery) {
                                _LastQuery = _.assign(_LastQuery, extraQuery, { start_: 0 });
                            }
                            else {
                                _LastQuery = query;
                            }
                            _current = Math.ceil(_LastQuery.start_ / _LastQuery.count_) + 1;
                            _c.label = 1;
                        case 1:
                            _c.trys.push([1, 6, , 7]);
                            return [4 /*yield*/, Ajax_1.default.POST(apis.query, _LastQuery)];
                        case 2:
                            resp = _c.sent();
                            if (!(resp.code === null || resp.code == '0')) return [3 /*break*/, 4];
                            return [4 /*yield*/, put({
                                    type: '_list',
                                    list: resp.list,
                                    total: resp.total,
                                    _current: _current,
                                })];
                        case 3:
                            _c.sent();
                            if (callback)
                                callback(resp);
                            return [3 /*break*/, 5];
                        case 4:
                            antd_1.message.error(React.createElement(React.Fragment, null,
                                objectName,
                                "\u67E5\u8BE2\u5931\u8D25"));
                            _c.label = 5;
                        case 5: return [3 /*break*/, 7];
                        case 6:
                            e_2 = _c.sent();
                            antd_1.message.error(React.createElement(React.Fragment, null,
                                objectName,
                                "\u67E5\u8BE2\u5931\u8D25"));
                            return [3 /*break*/, 7];
                        case 7: return [2 /*return*/];
                    }
                });
            },
            //说明：需要使用 Ajax 队列功能的方法 需要为 *function 类型，这样可以使用 yield 获取值
            //增加一个用户
            _add: function (_a, _b) {
                var param, resp;
                var data = _a.data, callback = _a.callback;
                var put = _b.put;
                return __generator(this, function (_c) {
                    switch (_c.label) {
                        case 0:
                            if (!_.has(apis, 'add')) {
                                return [2 /*return*/];
                            }
                            ;
                            param = _.assign({}, data);
                            if (pre) {
                                param = pre(param);
                            }
                            return [4 /*yield*/, Ajax_1.default.PUT(apis.add, param)];
                        case 1:
                            resp = _c.sent();
                            if (!(resp.code != '0')) return [3 /*break*/, 2];
                            antd_1.message.error(React.createElement(React.Fragment, null,
                                tip(data),
                                "\u521B\u5EFA\u5931\u8D25",
                                resp.message ? " : " + resp.message : ''));
                            return [3 /*break*/, 9];
                        case 2:
                            antd_1.message.success(React.createElement(React.Fragment, null,
                                tip(data),
                                "\u521B\u5EFA\u6210\u529F"));
                            if (!(_.has(resp, 'data') && !_.isEmpty(resp.data))) return [3 /*break*/, 7];
                            if (!(_.isString(resp.data) || _.isNumber(resp.data))) return [3 /*break*/, 4];
                            data[rowKey] = resp.data;
                            return [4 /*yield*/, put({
                                    type: '_doAdd',
                                    data: data
                                })];
                        case 3:
                            _c.sent();
                            return [3 /*break*/, 6];
                        case 4: return [4 /*yield*/, put({
                                type: '_doAdd',
                                data: resp.data
                            })];
                        case 5:
                            _c.sent();
                            _c.label = 6;
                        case 6: return [3 /*break*/, 9];
                        case 7: return [4 /*yield*/, put({
                                type: '_doAdd',
                                data: data
                            })];
                        case 8:
                            _c.sent();
                            _c.label = 9;
                        case 9:
                            if (callback)
                                callback(data, resp);
                            return [2 /*return*/];
                    }
                });
            },
            //修改一个用户        
            _update: function (_a, _b) {
                var param, resp, uData;
                var data = _a.data, callback = _a.callback;
                var put = _b.put;
                return __generator(this, function (_c) {
                    switch (_c.label) {
                        case 0:
                            if (!_.has(apis, 'update')) {
                                return [2 /*return*/];
                            }
                            ;
                            param = _.assign({}, data);
                            if (pre) {
                                param = pre(param);
                            }
                            return [4 /*yield*/, Ajax_1.default.PATCH(apis.update, param)];
                        case 1:
                            resp = _c.sent();
                            if (!(resp.code != '0')) return [3 /*break*/, 2];
                            antd_1.message.error(React.createElement(React.Fragment, null,
                                tip(data),
                                "\u4FEE\u6539\u5931\u8D25",
                                resp.message ? " : " + resp.message : ''));
                            return [3 /*break*/, 4];
                        case 2:
                            antd_1.message.success(React.createElement(React.Fragment, null,
                                tip(data),
                                "\u4FEE\u6539\u6210\u529F"));
                            uData = _.extend({}, data);
                            if (_.has(resp, 'data')) {
                                uData = _.extend(uData, resp.data);
                            }
                            return [4 /*yield*/, put({ type: '_doUpdate', data: uData })];
                        case 3:
                            _c.sent();
                            _c.label = 4;
                        case 4:
                            if (callback)
                                callback(data, resp);
                            return [2 /*return*/];
                    }
                });
            },
            //批量删除
            _delete: function (_a, _b) {
                var resp, resp;
                var data = _a.data, callback = _a.callback;
                var put = _b.put;
                return __generator(this, function (_c) {
                    switch (_c.label) {
                        case 0:
                            if (!_.has(apis, 'del')) {
                                return [2 /*return*/];
                            }
                            ;
                            if (!_.isArray(data)) return [3 /*break*/, 5];
                            return [4 /*yield*/, Ajax_1.default.DELETE(apis.del, { ids: data.join(',') })];
                        case 1:
                            resp = _c.sent();
                            if (!(resp.code != '0')) return [3 /*break*/, 2];
                            antd_1.message.error(React.createElement(React.Fragment, null,
                                objectName,
                                "\u5220\u9664\u5931\u8D25",
                                resp.message ? " : " + resp.message : ''));
                            return [3 /*break*/, 4];
                        case 2:
                            // message.success(<React.Fragment>{tip(data)}修改成功</React.Fragment>);
                            antd_1.message.success(data.length + "\u4E2A" + objectName + "\u5DF2\u7ECF\u88AB\u5220\u9664");
                            if (callback)
                                callback(data, resp);
                            return [4 /*yield*/, put({
                                    type: '_doDelete',
                                    data: data
                                })];
                        case 3:
                            _c.sent();
                            _c.label = 4;
                        case 4: return [3 /*break*/, 9];
                        case 5: return [4 /*yield*/, Ajax_1.default.DELETE(apis.del, { ids: data[rowKey] })];
                        case 6:
                            resp = _c.sent();
                            if (!(resp.code != '0')) return [3 /*break*/, 7];
                            antd_1.message.error(React.createElement(React.Fragment, null,
                                tip(data),
                                "\u5220\u9664\u5931\u8D25",
                                resp.message ? " : " + resp.message : ''));
                            return [3 /*break*/, 9];
                        case 7:
                            antd_1.message.success(React.createElement(React.Fragment, null,
                                tip(data),
                                "\u5DF2\u7ECF\u88AB\u5220\u9664"));
                            if (callback)
                                callback(data, resp);
                            return [4 /*yield*/, put({
                                    type: '_doDelete',
                                    data: [data[rowKey]]
                                })];
                        case 8:
                            _c.sent();
                            _c.label = 9;
                        case 9: return [4 /*yield*/, put({ type: '_deleteFlush' })];
                        case 10:
                            _c.sent();
                            return [2 /*return*/];
                    }
                });
            },
            //最后一条数据自动往前一页
            _deleteFlush: function (_a, _b) {
                var _c, list, _current, total;
                var put = _b.put, select = _b.select;
                return __generator(this, function (_d) {
                    switch (_d.label) {
                        case 0: return [4 /*yield*/, select(function (state) { return state[modelName]; })];
                        case 1:
                            _c = _d.sent(), list = _c.list, _current = _c._current, total = _c.total;
                            if (list.length > 0) {
                                return [2 /*return*/];
                            }
                            if ((_current - 1) * _LastQuery.count_ == total) {
                                if (_current == 1) {
                                    return [2 /*return*/];
                                }
                                _LastQuery.start_ = _LastQuery.start_ - _LastQuery.count_;
                            }
                            return [4 /*yield*/, put({ type: '_query', query: _LastQuery })];
                        case 2:
                            _d.sent();
                            return [2 /*return*/];
                    }
                });
            }
        },
        reducers: {
            doLoad: doLoad,
            //添加成功后，将用户 push 到 模型里面
            _doAdd: function (state, _a) {
                var data = _a.data;
                return __assign({}, state, { list: add(state.list, data, rowKey), total: state.total + 1 });
            },
            //编辑成功后，将模型里面修改的用户进行 update
            _doUpdate: function (state, _a) {
                var data = _a.data;
                return __assign({}, state, { list: update(state.list, data, rowKey) });
            },
            //删除成功后，将模型里面对应的用户删掉
            _doDelete: function (state, _a) {
                var data = _a.data;
                return __assign({}, state, { list: del(state.list, data, rowKey), total: state.total - data.length });
            },
            //查询，将模型里面的用户重置为查到的
            _list: function (state, _a) {
                var list = _a.list, total = _a.total, _current = _a._current;
                return __assign({}, state, { list: list, total: total, _current: _current });
            },
        },
    };
    return model;
}
/**
 * 流式模型：可以通过下拉获取更多的数据
 */
var PullModel = /** @class */ (function () {
    function PullModel(config) {
        this.query = '';
        this.param = {};
        this.pageSize = 10;
        this.list = [];
        this.total = 0;
        this.context = null;
        this.loadingFn = function (e) { return e; };
        this.query = config.query;
        this.pageSize = config.pageSize || 10;
        this.loadingFn = config.onChange;
        this.context = config.context || null;
        _.extend(this.param, config.params);
    }
    PullModel.prototype.callBack = function (loading) {
        this.loadingFn.call(this.context, {
            loading: loading,
            hasMore: this.list.length < this.total,
            list: this.list,
        });
    };
    PullModel.prototype.reSearch = function (param) {
        this.total = 0;
        this.list = [];
        this.param = _.extend({}, param);
        this.next();
    };
    PullModel.prototype.next = function (size) {
        if (size === void 0) { size = this.pageSize; }
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        this.callBack(true);
                        return [4 /*yield*/, Ajax_1.default.POST(this.query, _.extend(this.param, { start_: this.list.length, count_: size }))];
                    case 1:
                        result = _a.sent();
                        if (result.code == '0') {
                            this.total = result.total;
                            this.list = _.concat([], this.list, result.list);
                            this.callBack(false);
                        }
                        else {
                            antd_1.message.error('失败');
                        }
                        return [2 /*return*/];
                }
            });
        });
    };
    return PullModel;
}());
exports.PullModel = PullModel;
exports.default = { add: add, update: update, del: del, doLoad: doLoad, BuildModel: BuildModel, PullModel: PullModel };
