"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 NProgress = require("nprogress");
var Cache_1 = require("./Cache");
var jquery_1 = require("jquery");
var DEFAULT_ERROR = { code: '9999', message: '系统繁忙，请稍后再试试', data: {}, list: [], total: 0 };
var ignoreEmptyString = false;
/**
 * @private
 */
var cleanParam = function (obj) {
    if (obj === void 0) { obj = {}; }
    var keys = Object.keys(obj);
    for (var i = 0, _i = keys.length; i < _i; i++) {
        if (obj[keys[i]] === null || (ignoreEmptyString && obj[keys[i]] === '')) {
            delete obj[keys[i]];
        }
        // else {
        //   //过滤百分号
        //   if (_.isString(obj[keys[i]])) obj[keys[i]] = obj[keys[i]].replace(/\%/g, '\\%');
        // }
    }
    return obj;
};
/**
 * @private
 */
var codeMessage = {
    200: '服务器成功返回请求的数据',
    201: '新建或修改数据成功。',
    202: '一个请求已经进入后台排队（异步任务）',
    204: '删除数据成功。',
    400: '发出的请求有错误，服务器没有进行新建或修改数据,的操作。',
    401: '用户没有权限（令牌、用户名、密码错误）。',
    403: '用户得到授权，但是访问是被禁止的。',
    404: '发出的请求针对的是不存在的记录，服务器没有进行操作',
    406: '请求的格式不可得。',
    410: '请求的资源被永久删除，且不会再得到的。',
    422: '当创建一个对象时，发生一个验证错误。',
    500: '服务器发生错误，请检查服务器',
    502: '网关错误',
    503: '服务不可用，服务器暂时过载或维护',
    504: '网关超时',
};
/**
 * @private
 */
var CACHE_URL = new Set();
/**
 * @private
 */
function request(url, options) {
    if (options === void 0) { options = { method: 'GET', headers: {}, body: null }; }
    var defaultOptions = {
        credentials: 'include',
    };
    var newOptions = __assign({}, defaultOptions, options);
    if (newOptions.method === 'POST' || newOptions.method === 'PUT' || newOptions.method === 'DELETE' || newOptions.method === 'PATCH') {
        newOptions.headers = __assign({ Accept: 'application/json', 'Content-Type': 'application/json; charset=utf-8' }, newOptions.headers);
        newOptions.body = JSON.stringify(cleanParam(newOptions.body));
    }
    NProgress.start();
    // @ts-ignore
    return fetch(url, newOptions)
        .then(function (response) {
        NProgress.done();
        if (response.status >= 200 && response.status < 300) {
            return response.json();
        }
        var errortext = codeMessage[response.status] || response.statusText;
        console.error("\u9519\u8BEF \u2191\u8BF7\u67E5\u770B\u4E0A\u9762\u94FE\u63A5\u2191 (" + newOptions.method + " " + url + " = " + response.status + ") : " + errortext);
        return new Promise(function (ok) {
            response.json().then(function (resp) {
                var result = _.assign({}, DEFAULT_ERROR, resp);
                ok(result);
            }, function () { return ok(DEFAULT_ERROR); });
        });
    });
}
/**
 * Ajax 工具类
*/
var default_1 = /** @class */ (function () {
    function default_1() {
    }
    default_1.ignoreEmptyString = function () {
        ignoreEmptyString = true;
    };
    /**
     * 发送 HTTP GET(同步) 请求，支持返回结果
     * 按 RESTFUL 规范说明 ： GET 通常用来获取特定不变的数据
     *
     * @param url 请求接口链接地址
     * @param cache 是否缓存，默认缓存
     * @returns JSON对象
     *
     * 代码示例：
     * ```javascript
     * // 通过 回调函数 使用
     * import {Ajax} from 'utils'
     * Ajax.GETASYNC('/api-url');
     * Ajax.GETASYNC('/api-url',false);
     *
     * ```
    */
    default_1.GETASYNC = function (url, cache) {
        if (cache === void 0) { cache = true; }
        var result = Cache_1.default.sessionData(url);
        if (result) {
            return result;
        }
        jquery_1.ajax(url, { async: false, method: 'GET' }).done(function (resp) {
            result = resp;
            if (cache && resp.code == '0') {
                if (!CACHE_URL.has(url)) {
                    CACHE_URL.add(url);
                }
                Cache_1.default.sessionData(url, result);
            }
        });
        return result;
    };
    /**
     * 发送 HTTP GET 请求，支持 **回调函数** 与 **异步队列** 方式进行请求
     * 按 RESTFUL 规范说明 ： GET 通常用来获取特定不变的数据
     *
     * @param url 请求接口链接地址
     * @param callback 回调函数，如果没有设置，则返回一个 Promise对象
     * @returns 如果没有指定回调函数，则返回一个 Promise对象
     *
     * 额外说明 ： GET 方法支持浏览器前端缓存，可以预先将需要缓存的地址通过 Ajax.SESSION() 方法传入，对于已经缓存的地址不会发出实际的网络请求
     *
     * 代码示例：
     * ```javascript
     * // 通过 回调函数 使用
     * import {Ajax} from 'utils'
     * Ajax.GET('/api-url',json=>console.log(json));
     *
     * // 通过 异步队列 使用
     * const all = yield Ajax.GET('/api-url');
     * console.log(all);
     * ```
    */
    default_1.GET = function (url, callback) {
        return __awaiter(this, void 0, void 0, function () {
            var json_1, data, json, data_1, resp;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!callback) return [3 /*break*/, 4];
                        if (!!CACHE_URL.has(url)) return [3 /*break*/, 2];
                        return [4 /*yield*/, request(url)];
                    case 1:
                        json_1 = _a.sent();
                        callback.call(null, json_1);
                        return [2 /*return*/];
                    case 2:
                        data = Cache_1.default.sessionData(url);
                        if (data) {
                            callback.call(null, data);
                            return [2 /*return*/];
                        }
                        return [4 /*yield*/, request(url)];
                    case 3:
                        json = _a.sent();
                        if (json.code == '0' || json.code === undefined) {
                            Cache_1.default.sessionData(url, json);
                        }
                        callback.call(null, json);
                        return [3 /*break*/, 5];
                    case 4:
                        if (!CACHE_URL.has(url)) {
                            return [2 /*return*/, request(url)];
                        }
                        data_1 = Cache_1.default.sessionData(url);
                        if (data_1) {
                            return [2 /*return*/, new Promise(function (resolve) {
                                    resolve(data_1);
                                })];
                        }
                        resp = request(url);
                        resp.then(function (json) {
                            if (json.code == '0' || json.code === undefined) {
                                Cache_1.default.sessionData(url, json);
                            }
                        });
                        return [2 /*return*/, resp];
                    case 5: return [2 /*return*/];
                }
            });
        });
    };
    /**
     * 发送 HTTP POST 请求，支持 **回调函数** 与 **异步队列** 方式进行请求
     * 按 RESTFUL 规范说明 ： POST 通常用来做复杂的条件查询
     *
     * @param url 请求接口链接地址
     * @param param 请求参数，调用时会参数的 `json格式` 传给接口
     * @param callback 回调函数，如果没有设置，则返回一个 Promise对象
     * @returns 如果没有指定回调函数，则返回一个 Promise对象
     *
     * 代码示例：
     * ```javascript
     * // 通过 回调函数 使用
     * import {Ajax} from 'utils'
     * Ajax.POST('/api-url',{status:0,find:'name'},json=>console.log(json));
     *
     * // 通过 异步队列 使用
     * const resp = yield Ajax.POST('/api-url',{status:0,find:'name'});
     * console.log(resp);
     * ```
    */
    default_1.POST = function (url, param, callback) {
        return __awaiter(this, void 0, void 0, function () {
            var json;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!callback) return [3 /*break*/, 2];
                        return [4 /*yield*/, request(url, {
                                method: 'POST',
                                body: param
                            })];
                    case 1:
                        json = _a.sent();
                        callback.call(null, json);
                        return [3 /*break*/, 3];
                    case 2: return [2 /*return*/, request(url, {
                            method: 'POST',
                            body: param
                        })];
                    case 3: return [2 /*return*/];
                }
            });
        });
    };
    /**
     * 同步POST方法，仅供特殊场景使用
     * 一般场景避免使用，以免卡死
     */
    default_1.POSTASYNC = function (url, param) {
        var result = {};
        jquery_1.ajax(url, {
            async: false,
            method: 'POST',
            contentType: "application/json",
            data: JSON.stringify(cleanParam(param))
        })
            .done(function (resp) { result = resp; });
        return result;
    };
    /**
     * 发送 HTTP PUT 请求，支持 **回调函数** 与 **异步队列** 方式进行请求
     * 按 RESTFUL 规范说明 ： PUT 通常用来做对象的新增
     *
     * @param url 请求接口链接地址
     * @param param 请求参数，调用时会参数的 `json格式` 传给接口
     * @param callback 回调函数，如果没有设置，则返回一个 Promise对象
     * @returns 如果没有指定回调函数，则返回一个 Promise对象
     *
     * 代码示例：
     * ```javascript
     * // 通过 回调函数 使用
     * import {Ajax} from 'utils'
     * Ajax.PUT('/api-url',{status:0,find:'name'},json=>console.log(json));
     *
     * // 通过 异步队列 使用
     * const resp = yield Ajax.PUT('/api-url',{status:0,find:'name'});
     * console.log(resp);
     * ```
    */
    default_1.PUT = function (url, param, callback) {
        return __awaiter(this, void 0, void 0, function () {
            var json;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!callback) return [3 /*break*/, 2];
                        return [4 /*yield*/, request(url, {
                                method: 'PUT',
                                body: param
                            })];
                    case 1:
                        json = _a.sent();
                        callback.call(null, json);
                        return [3 /*break*/, 3];
                    case 2: return [2 /*return*/, request(url, {
                            method: 'PUT',
                            body: param
                        })];
                    case 3: return [2 /*return*/];
                }
            });
        });
    };
    /**
     * 发送 HTTP PATCH 请求，支持 **回调函数** 与 **异步队列** 方式进行请求
     * 按 RESTFUL 规范说明 ： PATCH 通常用来做对象的修改
     *
     * @param url 请求接口链接地址
     * @param param 请求参数，调用时会参数的 `json格式` 传给接口
     * @param callback 回调函数，如果没有设置，则返回一个 Promise对象
     * @returns 如果没有指定回调函数，则返回一个 Promise对象
     *
     * 代码示例：
     * ```javascript
     * // 通过 回调函数 使用
     * import {Ajax} from 'utils'
     * Ajax.PATCH('/api-url',{status:0,find:'name'},json=>console.log(json));
     *
     * // 通过 异步队列 使用
     * const resp = yield Ajax.PATCH('/api-url',{status:0,find:'name'});
     * console.log(resp);
     * ```
    */
    default_1.PATCH = function (url, param, callback) {
        return __awaiter(this, void 0, void 0, function () {
            var json;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!callback) return [3 /*break*/, 2];
                        return [4 /*yield*/, request(url, {
                                method: 'PATCH',
                                body: param
                            })];
                    case 1:
                        json = _a.sent();
                        callback.call(null, json);
                        return [3 /*break*/, 3];
                    case 2: return [2 /*return*/, request(url, {
                            method: 'PATCH',
                            body: param
                        })];
                    case 3: return [2 /*return*/];
                }
            });
        });
    };
    /**
     * 发送 HTTP DELETE 请求，支持 **回调函数** 与 **异步队列** 方式进行请求
     * 按 RESTFUL 规范说明 ： DELETE 通常用来做对象的删除
     *
     * @param url 请求接口链接地址
     * @param param 请求参数，调用时会参数的 `json格式` 传给接口
     * @param callback 回调函数，如果没有设置，则返回一个 Promise对象
     * @returns 如果没有指定回调函数，则返回一个 Promise对象
     *
     * 代码示例：
     * ```javascript
     * // 通过 回调函数 使用
     * import {Ajax} from 'utils'
     * Ajax.DELETE('/api-url',{status:0,find:'name'},json=>console.log(json));
     *
     * // 通过 异步队列 使用
     * const resp = yield Ajax.DELETE('/api-url',{status:0,find:'name'});
     * console.log(resp);
     * ```
    */
    default_1.DELETE = function (url, param, callback) {
        return __awaiter(this, void 0, void 0, function () {
            var json;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!callback) return [3 /*break*/, 2];
                        return [4 /*yield*/, request(url, {
                                method: 'DELETE',
                                body: param
                            })];
                    case 1:
                        json = _a.sent();
                        callback.call(null, json);
                        return [3 /*break*/, 3];
                    case 2: return [2 /*return*/, request(url, {
                            method: 'DELETE',
                            body: param
                        })];
                    case 3: return [2 /*return*/];
                }
            });
        });
    };
    /**
     * 请多个请求一起返回了再处理，两个以上请求时，可以使用
     * @param  异步请求列表
     * 示例
     * ```
      Ajax.WHEN(
          Ajax.GET('/api-common/user'),
          Ajax.GET('/api-common/user/ip'),
          Ajax.POST('/api-common/user',{})
      ).then(function(resp){
          console.log(resp[0],resp[1],resp[2]);
      });
     * ```
    */
    default_1.WHEN = function () {
        var pos = [];
        for (var _a = 0; _a < arguments.length; _a++) {
            pos[_a] = arguments[_a];
        }
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_b) {
                return [2 /*return*/, Promise.all(pos)];
            });
        });
    };
    /**
     * 注册需要缓存的链接地址
     * 此URL 在一次打开的过程中只会请求一次，
     * @param urls 接口地址列表，只支持 GET 接口
     * 如果需要清除，可以调用 Ajax.CLEAR(url) 来清除
     * 示例
     * ```
     * Ajax.SESSION('/url1','/url2','/url3');
     * Ajax.GET('/url1');
     * Ajax.GET('/url1');
     * Ajax.GET('/url1');
     * Ajax.CLEAR('/url1','/url2');
     * ```
     *
    */
    default_1.SESION = function () {
        var urls = [];
        for (var _a = 0; _a < arguments.length; _a++) {
            urls[_a] = arguments[_a];
        }
        urls.map(function (url) {
            if (!CACHE_URL.has(url)) {
                CACHE_URL.add(url);
            }
        });
    };
    ;
    /**
     * 清除接口本地缓存
     * @param urls 接口地址列表，只支持 GET 接口
     * 如果需要清除，可以调用 Ajax.CLEAR(url) 来清除
     * 示例
     * ```
     * Ajax.SESSION('/url1','/url2','/url3');
     * Ajax.GET('/url1');
     * Ajax.GET('/url1');
     * Ajax.GET('/url1');
     * Ajax.CLEAR('/url1','/url2');
     * ```
     *
    */
    default_1.CLEAR = function () {
        var urls = [];
        for (var _a = 0; _a < arguments.length; _a++) {
            urls[_a] = arguments[_a];
        }
        urls.map(function (url) {
            Cache_1.default.sessionDelete(url);
        });
    };
    /**
     *  一个等待的方法，通常用于 effect 里面延迟
    */
    default_1.WAIT = function (seconds) {
        if (seconds === void 0) { seconds = 1000; }
        return new Promise(function (resolve) {
            window.setTimeout(function () { return resolve(); }, seconds);
        });
    };
    default_1.UPLOAD = function (file, callback, param, url) {
        if (url === void 0) { url = '/api-servicesys/fileup/uploadFile'; }
        NProgress.start();
        var xhr = new XMLHttpRequest();
        var data = new FormData();
        data.append('file', file);
        // data.append('namespace', namespace);
        if (param) {
            if (param.namespace)
                data.append('namespace', param.namespace);
            if (param.userId)
                data.append('userId', param.userId);
            if (param.userName)
                data.append('userName', param.userName);
        }
        var successFn = function (response) {
            // 假设服务端直接返回文件上传后的地址
            // 上传成功后调用param.success并传入上传后的文件地址
            NProgress.done();
            callback.success(JSON.parse(xhr.responseText));
        };
        var progressFn = function (event) {
            // console.log(event.loaded / event.total * 100);
            if (callback.progress)
                callback.progress(event.loaded / event.total * 100);
            // 上传进度发生变化时调用param.progress
            // callback.progress(event.loaded / event.total * 100)
        };
        var errorFn = function (response) {
            NProgress.done();
            if (callback.error)
                callback.error(response);
            // 上传发生错误时调用param.error
            // callback.error({
            //   msg: 'unable to upload.'
            // })
        };
        xhr.upload.addEventListener("progress", progressFn, false);
        xhr.addEventListener("load", successFn, false);
        xhr.addEventListener("error", errorFn, false);
        xhr.addEventListener("abort", errorFn, false);
        xhr.open('POST', url, true);
        xhr.send(data);
    };
    return default_1;
}());
exports.default = default_1;
// export default { GET, POST, PUT, PATCH, DELETE, WHEN,SESION,CLEAR }
