/*!
 * @kt/request v1.1.0 
 * https://ktcode.keytop.cn/front-framework/kt/request.git
 * (c) 2022 @wangzhifeng
 * Released under the MIT License.
 */
import axios from 'axios';
import { merge } from 'lodash-es';

var config = {
    nodeEnv: 'development',
    customEnv: 'test',
    printLog: true,
    mobile: false,
    showModal: function (message) { },
    showToast: function (message) { },
    showLoading: {
        show: function () { },
        hide: function () { }
    },
    strategies: {},
    branches: {},
    customCode: {
        custom: 4400,
        canceled: 4401
    }
};

/*! *****************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

var __assign = function() {
    __assign = Object.assign || function __assign(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);
};

function __awaiter(thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
}

function __generator(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 };
    }
}

/**
 * 通用配置
 */
function common(branch, config) {
    return {
        request: function (method, contentType, headers, parameters, ext) {
            var nodeAPIConfig = {};
            /**
             * 从参数中提取 nodeAPIConfig 配置当前接口全局相关。
             * 接口包目前已经更新，新增 ext 在方法参数尾部，所以暂时不用这种比较不友好的方式，
             * 但是目前还是做了兼容处理
             */
            if (parameters.nodeAPIConfig) {
                nodeAPIConfig = parameters.nodeAPIConfig;
                Reflect.deleteProperty(parameters, 'nodeAPIConfig');
            }
            else if (ext) {
                nodeAPIConfig = ext;
            }
            method = method.toLowerCase();
            // 判断当前是上传文件相关接口
            // method = contentType === 'multipart/form-data' ? 'upload' : method;
            // @ts-ignore
            return request[branch][method]('', parameters, merge({
                headers: Object.assign({ 'Content-Type': contentType }, headers)
            }, 
            // 分支级
            config, 
            // 接口级
            nodeAPIConfig));
        }
    };
}

var pending = new Map();
var _id = function (config) {
    var _a, _b;
    return [
        config.method,
        config.url,
        JSON.stringify(config.params),
        JSON.stringify(config.data),
        // node 接口包的参数 url 用 headers 的 pid 和 sid 表示
        JSON.stringify((_a = config.headers) === null || _a === void 0 ? void 0 : _a.pid),
        JSON.stringify((_b = config.headers) === null || _b === void 0 ? void 0 : _b.sid)
    ].join('&');
};
var addPending = function (config) {
    var id = _id(config);
    config.cancelToken =
        config.cancelToken ||
            new axios.CancelToken(function (cancel) {
                if (!pending.has(id)) {
                    pending.set(id, cancel);
                }
            });
};
var removePending = function (config) {
    var id = _id(config);
    if (pending.has(id)) {
        var cancel = pending.get(id);
        cancel(id);
        pending.delete(id);
    }
};

var parseCode = function (code) {
    return code !== undefined && code !== null && code !== ''
        ? isNaN(+code)
            ? code
            : +code
        : code;
};
var undefinedOrTrueIsTrue = function (val) {
    return val !== null && val !== void 0 ? val : true;
};
/**
 * 打印接口消息，移动端采用简单打印的方式
 */
var printLog = function (config$1, data, error) {
    var _a;
    if (error === void 0) { error = ''; }
    if (!config.printLog) {
        return;
    }
    var _action = ((_a = config$1.url) === null || _a === void 0 ? void 0 : _a.indexOf('/')) === 0 ? config$1.url.substring(1) : "".concat(config$1.url);
    var headers = config$1.headers, branch = config$1.branch;
    var _printPC = function () {
        console.group("%c".concat(branch, ".Action\uFF1A"), 'background:#00b38a;color:#fff', _action || "sid\uFF1A".concat((headers === null || headers === void 0 ? void 0 : headers.sid) || ''));
        config.branches[config$1.branch].origin[config.customEnv];
        (branch === null || branch === void 0 ? void 0 : branch.indexOf('node-')) === -1 &&
            console.log('%cURL：', 'color:#00b38a', "".concat(config.nodeEnv === 'production'
                ? config.branches[config$1.branch].origin[config.customEnv]
                : window.location.origin, "/").concat(_action));
        console.log('%cMethod：', 'color:#00b38a', config$1.method);
        console.log('%cIn-Params：', 'color:#00b38a', config$1.params || config$1.data);
        console.log('%cOut-Params：', 'color:#00b38a', data);
        error !== '' && console.log('%cError：', 'color:#ff0000', error);
        console.groupEnd();
    };
    var _printMobile = function () {
        console.log('#region');
        console.log("".concat(branch, ".Action\uFF1A"), _action || "sid\uFF1A".concat((headers === null || headers === void 0 ? void 0 : headers.sid) || ''));
        (branch === null || branch === void 0 ? void 0 : branch.indexOf('node-')) === -1 &&
            console.log('URL：', "".concat(config.nodeEnv === 'production'
                ? config.branches[config$1.branch].origin[config.customEnv]
                : window.location.origin, "/").concat(_action));
        console.log('Method：', config$1.method);
        console.log('In-Params：', config$1.params || config$1.data);
        console.log('Out-Params：', data);
        error !== '' && console.log('Error：', error);
        console.log('#endregion');
        console.log('');
    };
    if (!config.mobile) {
        _printPC();
    }
    else {
        _printMobile();
    }
};

var Validator = /** @class */ (function () {
    function Validator() {
        Object.defineProperty(this, "cache", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        this.cache = {};
    }
    /**
     * 新增分支策略，rules 可能为空
     */
    Object.defineProperty(Validator.prototype, "add", {
        enumerable: false,
        configurable: true,
        writable: true,
        value: function (branch, rules) {
            var _this = this;
            if (rules === void 0) { rules = []; }
            this.cache[branch] = [];
            for (var i = 0, len = rules.length; i < len; i++) {
                (function (rule) {
                    _this.cache[branch].push(function (data, config$1) {
                        var _a, _b;
                        var codeKey = rule.codeKey, codeValue = rule.codeValue, msgKey = rule.msgKey;
                        // 将对应的 code 标识统一转换整数，方便用 === 判断 code
                        data[codeKey] = parseCode(data[codeKey]);
                        return (_b = (_a = config.strategies)[rule.strategy]) === null || _b === void 0 ? void 0 : _b.call(_a, {
                            branch: branch,
                            data: data,
                            config: config$1,
                            codeKey: codeKey,
                            codeValue: codeValue,
                            msgKey: msgKey,
                            showModal: config.showModal,
                            showToast: config.showToast
                        });
                    });
                })(rules[i]);
            }
            return this;
        }
    });
    /**
     * 开始验证，循环配置的策略数组
     * ✨ 如果策略是一个异步，这里要用 await 来保证每个策略都会被穷举
     */
    Object.defineProperty(Validator.prototype, "start", {
        enumerable: false,
        configurable: true,
        writable: true,
        value: function (branch, data, config) {
            return __awaiter(this, void 0, void 0, function () {
                var arr, validator, i, len;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            arr = this.cache[branch];
                            if (!(arr && arr.length > 0)) return [3 /*break*/, 4];
                            validator = void 0;
                            i = 0, len = arr.length;
                            _a.label = 1;
                        case 1:
                            if (!(i < len)) return [3 /*break*/, 4];
                            validator = arr[i];
                            // 保证当前策略先执行完，再进入下一个
                            return [4 /*yield*/, validator(data, config)];
                        case 2:
                            // 保证当前策略先执行完，再进入下一个
                            _a.sent();
                            _a.label = 3;
                        case 3:
                            i++;
                            return [3 /*break*/, 1];
                        case 4: return [2 /*return*/];
                    }
                });
            });
        }
    });
    Object.defineProperty(Validator.prototype, "get", {
        enumerable: false,
        configurable: true,
        writable: true,
        value: function () {
            return this.cache;
        }
    });
    return Validator;
}());

var validator = new Validator();

var defaultLang = {
    KTRequest: {
        timeout: '请求超时，请稍后再试',
        networkErr: '您的网络好像断开了哦~',
        responseErr: '请求返回时发生错误',
        defaultErr: '服务器返回失败/请求接口错误'
    }
};

// import { getCurrentInstance } from 'vue';
var t = function () {
    var args = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        args[_i] = arguments[_i];
    }
    // const instance = getCurrentInstance();
    // @ts-ignore
    // const $t = instance?.$t;
    console.log('baseConfig.$t :>> ', config.$t);
    // 如果当前项目有 i18n 的$t方法注入，就使用它
    if (config.$t)
        return config.$t.apply(config, args);
    var path = args[0];
    var arr = path.split('.');
    var current = defaultLang, value = '', key;
    for (var i = 0, len = arr.length; i < len; i++) {
        key = arr[i];
        value = current[key];
        if (i === len - 1)
            return value;
        if (!value)
            return '';
        current = value;
    }
    return '';
};

var request = {};
/**
 * 主要请求方法
 */
var requestMain = function (config$1, ext) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
    var branch = ext.branch, instance = ext.instance;
    // 获取该分支相关信息
    var currBranch = config.branches[branch];
    // proxy 只有分支级
    currBranch.proxy = undefinedOrTrueIsTrue(currBranch.proxy);
    // 预设 config 相关
    // 接口局部/分支级/默认
    config$1.customAuth = (_b = (_a = config$1.customAuth) !== null && _a !== void 0 ? _a : currBranch.customAuth) !== null && _b !== void 0 ? _b : true;
    config$1.codeErrTip = (_d = (_c = config$1.codeErrTip) !== null && _c !== void 0 ? _c : currBranch.codeErrTip) !== null && _d !== void 0 ? _d : true;
    config$1.rejectErrTip = (_f = (_e = config$1.rejectErrTip) !== null && _e !== void 0 ? _e : currBranch.rejectErrTip) !== null && _f !== void 0 ? _f : true;
    // 移动端默认 true
    config$1.loading = (_h = (_g = config$1.loading) !== null && _g !== void 0 ? _g : currBranch.loading) !== null && _h !== void 0 ? _h : !!config.mobile;
    // 默认不开启
    config$1.cancel = (_k = (_j = config$1.cancel) !== null && _j !== void 0 ? _j : currBranch.cancel) !== null && _k !== void 0 ? _k : false;
    // 标记分支名
    config$1.branch = branch;
    var baseURL = '';
    /**
     * 开发模式开启代理，nodeAPI 默认已经开启跨域，无需代理
     * 开发模式：重写 config.url，让 proxy 可命中处理，proxy=false 不开启代理（不用在 vue.config.js 中配置代理）
     * 正式模式：配置对应的 baseURL
     */
    if (config.nodeEnv !== 'production' && currBranch.proxy) {
        config$1.url = "/".concat(branch, "/").concat(config$1.url);
    }
    else {
        baseURL = currBranch.origin[config.customEnv];
    }
    // 在请求开始前，对之前的请求做检查取消操作
    config$1.cancel && removePending(config$1);
    // 将当前请求添加到 pending 中
    config$1.cancel && addPending(config$1);
    config$1.loading && config.showLoading.show();
    var requestConfig = merge(
    // 可被各个实例的拦截器重写配置
    {
        timeout: 20000,
        headers: {
            'Content-Type': 'application/json'
        }
    }, {
        baseURL: baseURL
    }, config$1);
    return instance
        .request(requestConfig)
        .then(function (res) {
        var data = res.data;
        // 在请求结束后，移除本次请求
        config$1.cancel && removePending(res.config);
        if (data && res.status === 200) {
            // 开始验证，错误将全局提示
            validator.start(branch, data, config$1);
            printLog(config$1, data);
            config$1.loading && config.showLoading.hide();
            return data;
        }
        return Promise.reject(new Error('Response Error'));
    })
        .catch(function (error) {
        var _a, _b;
        var retData = {
            code: (_a = config.customCode) === null || _a === void 0 ? void 0 : _a.custom,
            data: null,
            message: 'Custom Error',
            error: error
        };
        printLog(config$1, retData, error);
        config$1.loading && config.showLoading.hide();
        // 判断当前接口是否是被取消的
        if (axios.isCancel(error)) {
            retData.code = (_b = config.customCode) === null || _b === void 0 ? void 0 : _b.canceled;
            console.log('Request Canceled', error.message);
        }
        else if (error.message) {
            if (error.message.indexOf('timeout') !== -1) {
                // const message = '请求超时，请稍后再试';
                var message = t('KTRequest.timeout');
                config$1.rejectErrTip && config.showModal(message);
            }
            else if (error.message.indexOf('Network Error') !== -1) {
                // const message = '您的网络好像断开了哦~';
                var message = t('KTRequest.networkErr');
                config$1.rejectErrTip && config.showModal(message);
            }
            else if (error.message.indexOf('Response Error') !== -1) {
                // const message = '请求返回时发生错误';
                var message = t('KTRequest.responseErr');
                config$1.rejectErrTip && config.showModal(message);
            }
            else {
                // const message = '服务器返回失败/请求接口错误';
                var message = t('KTRequest.defaultErr');
                config$1.rejectErrTip && config.showModal(message);
            }
        }
        // 将错误以正确的方式返回，外部就不需要进行 try catch 包裹
        return Promise.resolve(retData);
    });
};
/**
 * 通用请求方法，统一请求入参格式，path, data, config
 */
var requestFn = function (ext) { return ({
    get: function (path, data, config) {
        return requestMain(__assign(__assign({}, config), { method: 'GET', url: path, params: data }), ext);
    },
    post: function (path, data, config) {
        return requestMain(__assign(__assign({}, config), { method: 'POST', url: path, data: data }), ext);
    },
    delete: function (path, data, config) {
        return requestMain(__assign(__assign({}, config), { method: 'DELETE', url: path, params: data }), ext);
    },
    put: function (path, data, config) {
        return requestMain(__assign(__assign({}, config), { method: 'PUT', url: path, data: data }), ext);
    }
}); };
/**
 * 初始化所有请求实例，依赖 baseConfig 的初始化，需要在初始化之后调用
 */
var initInstance = function () {
    var instance;
    var instance2;
    for (var _i = 0, _a = Object.entries(config.branches); _i < _a.length; _i++) {
        var _b = _a[_i], branch = _b[0], value = _b[1];
        instance = axios.create();
        if (branch === 'master') {
            // 引用赋值的方式
            Object.assign(request, instance);
            // @ts-ignore
            instance2 = request;
        }
        else {
            // @ts-ignore
            instance2 = request[branch] = instance;
            // node 接口包，特殊处理
            if (branch.indexOf('node-') === 0) {
                // node 接口默认跨域，不代理
                value.proxy = false;
                value.msConfig.use(common(branch));
            }
        }
        // 外部 request 方法扩展
        if (value.requestExtend) {
            var _loop_1 = function (key, fn) {
                value.requestExtend[key] = (function (_a) {
                    var instance = _a.instance, branch = _a.branch;
                    // @ts-ignore
                    return function (path, data, config) {
                        // @ts-ignore
                        var conf = fn(path, data, config);
                        return requestMain(conf, { instance: instance, branch: branch });
                    };
                })({ instance: instance, branch: branch });
            };
            for (var _c = 0, _d = Object.entries(value.requestExtend); _c < _d.length; _c++) {
                var _e = _d[_c], key = _e[0], fn = _e[1];
                _loop_1(key, fn);
            }
        }
        Object.assign(instance2, requestFn({ instance: instance, branch: branch }), value.requestExtend);
    }
};

// install 方法，用来初始化配置
Object.defineProperty(request, 'install', {
    value: function (app, options) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
        // 重写
        Object.assign(config, {
            mobile: (_a = options.mobile) !== null && _a !== void 0 ? _a : config.mobile,
            printLog: (_b = options.printLog) !== null && _b !== void 0 ? _b : config.printLog,
            nodeEnv: (_c = options.nodeEnv) !== null && _c !== void 0 ? _c : config.nodeEnv,
            customEnv: (_d = options.customEnv) !== null && _d !== void 0 ? _d : config.customEnv,
            strategies: (_e = options.strategies) !== null && _e !== void 0 ? _e : config.strategies,
            branches: (_f = options.branches) !== null && _f !== void 0 ? _f : config.branches,
            customCode: (_g = options.customCode) !== null && _g !== void 0 ? _g : config.customCode,
            showModal: (_h = options.showModal) !== null && _h !== void 0 ? _h : config.showModal,
            showToast: (_j = options.showToast) !== null && _j !== void 0 ? _j : config.showToast,
            showLoading: (_k = options.showLoading) !== null && _k !== void 0 ? _k : config.showLoading,
            $t: options.$t
        });
        Object.assign(customCode, config.customCode);
        // 初始化验证器
        for (var _i = 0, _m = Object.entries(options.branches); _i < _m.length; _i++) {
            var _o = _m[_i], key = _o[0], value = _o[1];
            validator.add(key, value.validator);
        }
        // 初始化请求实例
        initInstance();
        // 注入到 Vue3 全局
        if ((_l = app === null || app === void 0 ? void 0 : app.config) === null || _l === void 0 ? void 0 : _l.globalProperties) {
            app.config.globalProperties.$request = request;
        }
    }
});
/**
 * 暴露自定义错误 code 对象
 */
var customCode = config.customCode;

export { customCode, request as default };
