"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getNetworkType = exports.simpleCheckAdminPortal = exports.commonReport = exports.reportEvent = exports.reportTime = exports.isEqual = exports.serde = exports.isEnableWecom = exports.setEnableWecom = exports.ENABLE_WECOM = exports.setEnablePageRoot = exports.ENABLE_PAGE_ROOT_ID = exports.setEnableObserverRef = exports.ENABLE_OBSERVER_REF = exports.generateDataContext = exports.redirectToLogin = exports.defaultGenerateLoginUrl = exports.checkAuth = exports.formatErrorMsg = exports.checkAnonymous = exports.getAuthConfig = exports.dealCache = exports.findLoginPage = exports.getScopeSlotMeta = exports.isSlot = exports.isPlainObject = exports.isEmptyObj = exports.camelcase = exports.kebabCase = exports.bindFuncObj = exports.resolveDataBinds = void 0;
const tslib_1 = require("tslib");
const cals_1 = require("@cloudbase/cals");
const global_api_1 = require("../app/global-api");
const weda_client_1 = require("@cloudbase/weda-client");
const helper_1 = require("./sso/helper");
const init_1 = require("./sso/init");
const lodash_es_1 = require("lodash-es");
const { loginScope, getAccessToken } = weda_client_1.auth;
/**
 * All data bindings are generated as functions: (forItems) => any
 * @param {*} dataBinds
 * @param {*} forItems
 */
function resolveDataBinds(dataBinds, forItems, codeContext, scopeContext, throwError, dataContext, $w, paramsContext) {
    const resolvedProps = {};
    for (const prop in dataBinds) {
        let fn = dataBinds[prop];
        try {
            if (codeContext === null || codeContext === void 0 ? void 0 : codeContext.$WEAPPS_COMP) {
                fn = fn.bind(codeContext.$WEAPPS_COMP);
            }
            resolvedProps[prop] = fn(forItems, codeContext === null || codeContext === void 0 ? void 0 : codeContext.event, dataContext, $w, scopeContext, paramsContext);
        }
        catch (e) {
            console.error('Error resolving data binding', prop, dataBinds[prop], e);
            if (throwError) {
                throw e;
            }
        }
    }
    return resolvedProps;
}
exports.resolveDataBinds = resolveDataBinds;
/**
 * 对函数进行批量绑定
 * @param {*} funcObj
 * @param {*} context
 */
function bindFuncObj(funcObj = {}, context) {
    return Object.keys(funcObj).reduce((obj, fnName) => {
        var _a, _b;
        obj[fnName] = (_b = (_a = funcObj[fnName]) === null || _a === void 0 ? void 0 : _a.bind) === null || _b === void 0 ? void 0 : _b.call(_a, context);
        return obj;
    }, {});
}
exports.bindFuncObj = bindFuncObj;
function kebabCase(str) {
    return str.replace(/[A-Z]/g, (match) => {
        return `-${match.toLowerCase()}`;
    });
}
exports.kebabCase = kebabCase;
function camelcase(str, firstUpperCase = false) {
    str = str.replace(/[_-]([a-z])/g, (l) => {
        return l[1].toUpperCase();
    });
    if (firstUpperCase)
        str = str.charAt(0).toUpperCase() + str.slice(1);
    return str;
}
exports.camelcase = camelcase;
const isEmptyObj = (obj) => {
    if (!isPlainObject(obj)) {
        return false;
    }
    for (const i in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, i)) {
            return false;
        }
    }
    return true;
};
exports.isEmptyObj = isEmptyObj;
function isPlainObject(src) {
    return Object.prototype.toString.call(src) === '[object Object]';
}
exports.isPlainObject = isPlainObject;
/**
 * @deprecated
 * 历史静态配置，不再新增
 */
const SCOPE_SLOT_COMPONENT_LIB = ['tea_basis', 'tea_shop', 'crm_basis'];
/**
 * @deprecated
 * 历史静态配置，不再新增
 */
const SCOPE_SLOT_MAP = SCOPE_SLOT_COMPONENT_LIB.reduce((map, lib) => {
    map[`${lib}:TableMatching`] = {
        headerSlot: true,
        recordSlot: true,
    };
    map[`${lib}:TableExpanded`] = {
        headerSlot: true,
        recordSlot: true,
    };
    map[`${lib}:TabsTable`] = {
        headerSlot: true,
        recordSlot: true,
    };
    map[`${lib}:Table`] = {
        headerSlot: true,
        recordSlot: true,
    };
    return map;
}, {});
function isSlot(comp) {
    return !comp.module && !comp.component;
}
exports.isSlot = isSlot;
/**
 * 判断是否为作用域插槽
 * 1、根据组件dataForm是否有属性包含 x-slot-scope 属性
 * 2、保持历史穷举法不变
 */
function getScopeSlotMeta(comp, slot, context) {
    var _a, _b, _c;
    const sourceKey = comp.module && comp.component && `${comp.module}:${comp.component}`;
    const map = SCOPE_SLOT_MAP[sourceKey];
    const res = {
        isScopeSlot: (map === null || map === void 0 ? void 0 : map[slot]) || false,
        useScopeWidgetData: false,
        config: undefined,
    };
    const info = (_a = context === null || context === void 0 ? void 0 : context.componentsInfoMap) === null || _a === void 0 ? void 0 : _a[sourceKey];
    function updateScopeSlotMeta(prop, config) {
        var _a;
        res.isScopeSlot = true;
        res.useScopeWidgetData = true;
        res.config = Object.assign({}, config);
        if (sourceKey === 'CLOUDBASE_BUSSINESS:ModelTable') {
            res.useScopeWidgetData = false;
        }
        else if (comp.module === cals_1.OFFICIAL_LIB_KEY || comp.module === 'weda') {
            let gt = false;
            const properties = ((_a = info.properties) === null || _a === void 0 ? void 0 : _a.properties) || info.properties;
            if (comp.component === 'WdTable' && properties.records) {
                gt = true;
            }
            if (!gt) {
                res.useScopeWidgetData = false;
            }
        }
        /**
         * 首先 版本号确定使用新版
         * 其次 若无 for 配置 默认补足配置
         */
        if (res.useScopeWidgetData) {
            if ((sourceKey === `${cals_1.OFFICIAL_LIB_KEY}:WdTable` || sourceKey === `weda:WdTable`) &&
                (prop === 'cell' || prop === 'cell__custom__option') &&
                !res.config['x-slot-directives']) {
                res.config['x-slot-directives'] = {
                    for: 'records',
                    /**
                     * 没想好是记录 key 标识，用 find 去找
                     * 还是直接用 index 来
                     */
                    _index: 'recordIndex',
                };
            }
        }
    }
    try {
        const { dataForm } = info || {};
        if (typeof dataForm === 'object') {
            /**
             * 优先精确匹配
             * 然后模糊匹配
             */
            if ((_b = dataForm[slot]) === null || _b === void 0 ? void 0 : _b['x-slot-scope']) {
                updateScopeSlotMeta(slot, dataForm[slot]);
            }
            else {
                // eslint-disable-next-line no-restricted-syntax
                for (const prop in dataForm) {
                    if (slot.startsWith(`${prop}_`) && ((_c = dataForm[prop]) === null || _c === void 0 ? void 0 : _c['x-slot-scope'])) {
                        updateScopeSlotMeta(prop, dataForm[prop]);
                        break;
                    }
                }
            }
        }
    }
    catch (e) { }
    return res;
}
exports.getScopeSlotMeta = getScopeSlotMeta;
function findLoginPage(app = global_api_1.app) {
    const { pages = [] } = app.__internal__.getConfig();
    return pages.find((item) => item.type === 'login');
}
exports.findLoginPage = findLoginPage;
/**
 * JSON.parse封装
 * @param {*} data
 * @param {*} defaultValue 失败时返回到默认值
 * @returns
 */
const jsonParse = (data, defaultValue) => {
    try {
        return JSON.parse(data);
    }
    catch (err) {
        return defaultValue;
    }
};
/**
 * 缓存用户信息，非首次进入页面优先使用缓存
 * @param param0
 * @returns
 */
const dealCache = ({ key, cacheKey, value, type = 'get', }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
    var _a;
    if (!localStorage || !key)
        return undefined;
    try {
        const { clientId = '', envId = '', id } = global_api_1.app.__internal__.getConfig();
        cacheKey = `${envId}-${clientId}_${cacheKey || id}`;
        // 缓存值为对象，保证针对各环境各用户的信息唯一，{ [cacheKey]: { [userKey]: value } }
        yield global_api_1.app.cloud.getCloudInstance();
        const { accessToken = '' } = (yield getAccessToken()) || {};
        const userKey = `${accessToken}`;
        const cache = jsonParse(localStorage.getItem(key), {});
        if (type === 'get') {
            return (_a = cache[cacheKey]) === null || _a === void 0 ? void 0 : _a[userKey];
        }
        else if (type === 'set') {
            localStorage.setItem(key, JSON.stringify(Object.assign(Object.assign({}, cache), { [cacheKey]: { [userKey]: value } })));
        }
        else if (type === 'remove') {
            Object.keys(cache).forEach((key) => {
                if (key.startsWith(cacheKey)) {
                    delete cache[key];
                }
            });
            localStorage.setItem(key, JSON.stringify(cache));
        }
    }
    catch (error) {
        return undefined;
    }
});
exports.dealCache = dealCache;
const getAuthConfigRes = (app) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
    try {
        const res = yield app.cloud.callWedaApi({
            action: 'DescribeRuntimeResourceStrategy',
            data: {
                ResourceType: 'app',
                ResourceId: app.id,
            },
        });
        const settingData = {};
        // 云api不支持map只能传字符串，需要转换
        res === null || res === void 0 ? void 0 : res.forEach((item) => {
            settingData[item.Key] = ['AllowRegister', 'NeedLogin'].includes(item.Key) ? item.Value === '1' : item.Value;
        });
        (0, exports.dealCache)({ key: 'AUTH_CONFIG', cacheKey: app.id, value: settingData, type: 'set' });
        return settingData;
    }
    catch (e) {
        return {
            NeedLogin: false,
            RejectStrategy: 'show_warning',
        };
    }
});
function getAuthConfig(app = global_api_1.app) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const localCache = yield (0, exports.dealCache)({ key: 'AUTH_CONFIG', cacheKey: app.id, type: 'get' });
        if (localCache) {
            // 优先使用缓存，后更新缓存
            setTimeout(() => {
                getAuthConfigRes(app);
            }, 0);
            return localCache;
        }
        return yield getAuthConfigRes(app);
    });
}
exports.getAuthConfig = getAuthConfig;
const getAccessPermissionRes = ({ app, cacheKey, appId }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
    const res = yield app.cloud.callWedaApi({
        action: 'DescribeResourcesPermission',
        data: {
            ResourceType: `app`,
            ResourceIdList: [cacheKey],
            AppResourceId: appId,
        },
    });
    if (Array.isArray(res)) {
        const resourceInfo = res.find((i) => i.ResourceId === cacheKey);
        const value = {
            isAccess: !!(resourceInfo === null || resourceInfo === void 0 ? void 0 : resourceInfo.IsAccess),
            roleId: resourceInfo === null || resourceInfo === void 0 ? void 0 : resourceInfo.RoleId,
        };
        (0, exports.dealCache)({ key: 'RENDER_ACCESS', cacheKey, value, type: 'set' });
        return value;
    }
    else {
        throw new Error(`鉴权接口返回参数不正确 - ${JSON.stringify(res)}`);
    }
});
function getAccessPermission(app, appId, pageId) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const cacheKey = `${appId}-${pageId}`;
        const localCache = yield (0, exports.dealCache)({ key: 'RENDER_ACCESS', cacheKey, type: 'get' });
        if (localCache !== undefined) {
            // 延迟获取接口数据，让其他任务先执行
            setTimeout(() => {
                getAccessPermissionRes({ app, cacheKey, appId });
            }, 0);
            return localCache;
        }
        return yield getAccessPermissionRes({ app, cacheKey, appId });
    });
}
function checkAnonymous() {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        // 用户是否非匿名登录前端判断条件：有accessToken且scope不为anonymous
        // 此分支逻辑本不应该前端判断是否登录，历史原因后端短期内搞不定，后续后端优化后删除
        let isAnonymous = true;
        try {
            const [scope, { accessToken }] = yield Promise.all([loginScope(), getAccessToken()]);
            if (accessToken && scope !== 'anonymous') {
                isAnonymous = false;
            }
        }
        catch (e) { }
        return isAnonymous;
    });
}
exports.checkAnonymous = checkAnonymous;
function formatErrorMsg(e) {
    let msg = (e === null || e === void 0 ? void 0 : e.error_description) || (e === null || e === void 0 ? void 0 : e.message);
    const uri = e === null || e === void 0 ? void 0 : e.error_uri;
    msg = `${msg}${uri ? `-${uri}` : ''}`;
    if (msg.startsWith('Failed to fetch')) {
        msg = `网络故障, 请检查本地网络连接是否正常(${msg})`;
    }
    return msg;
}
exports.formatErrorMsg = formatErrorMsg;
/**
 * 检查页面权限
 **/
function checkAuth(app, appId, $page, generateLoginUrl) {
    var _a, _b;
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        app.showNavigationBarLoading();
        const { loginConfigVersion } = app.__internal__.getConfig();
        const requestList = [getAccessPermission(app, appId, $page.id)];
        // 有登录配置版本号时，才拉取自定义登录配置进行校验
        if (loginConfigVersion) {
            requestList.push(getAuthConfig(app));
            requestList.push(checkAnonymous());
        }
        try {
            const [accessData, authConfig, isAnonymous] = yield Promise.all(requestList);
            app.hideNavigationBarLoading();
            if (loginConfigVersion && isAnonymous) {
                if (authConfig.NeedLogin || (!(accessData === null || accessData === void 0 ? void 0 : accessData.isAccess) && authConfig.RejectStrategy === 'to_login')) {
                    redirectToLogin(generateLoginUrl);
                    return false;
                }
            }
            if (!(accessData === null || accessData === void 0 ? void 0 : accessData.isAccess)) {
                app.showToast({
                    title: ['-2', '-4'].includes(accessData === null || accessData === void 0 ? void 0 : accessData.roleId) ? '默认访客无权限' : '页面无访问权限',
                    icon: 'error',
                });
            }
            return accessData === null || accessData === void 0 ? void 0 : accessData.isAccess;
        }
        catch (e) {
            app.showModal({
                title: '页面鉴权失败',
                content: formatErrorMsg(e),
                showCancel: false,
            });
            // @ts-ignore
            (_b = (_a = window._aegis) === null || _a === void 0 ? void 0 : _a.error) === null || _b === void 0 ? void 0 : _b.call(_a, 'CUSTOM_ERROR:', e);
            return false;
        }
    });
}
exports.checkAuth = checkAuth;
const defaultGenerateLoginUrl = () => {
    return getLoginUrl();
};
exports.defaultGenerateLoginUrl = defaultGenerateLoginUrl;
function getLoginUrl() {
    const app = global_api_1.app;
    const { envId, id, clientId, loginConfigVersion } = app.__internal__.getConfig();
    return `${location.origin}/__auth/?redirect_uri=${encodeURIComponent(location.href)}&app_id=${id}&env_id=${envId}&client_id=${clientId}&config_version=${loginConfigVersion}`;
}
function redirectToLogin(generateLoginUrl) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const app = global_api_1.app;
        const { loginConfigVersion, id } = app.__internal__.getConfig();
        // 去登录则清空权限缓存。
        (0, exports.dealCache)({ key: 'RENDER_ACCESS', cacheKey: id, type: 'remove' });
        // 有登录配置版本号时，自定义登录开启，则跳转到自定义登录页面
        if (loginConfigVersion) {
            const url = generateLoginUrl({ app }, getLoginUrl);
            const alternative = function alternative() {
                app.redirectTo({
                    mode: 'web',
                    params: {},
                    url,
                });
            };
            if (exports.ENABLE_WECOM) {
                (0, init_1.tryWecomLogin)(new URL(url), alternative);
            }
            else {
                alternative();
            }
        }
        else {
            app.showToast({
                title: '用户未登录',
                icon: 'error',
            });
        }
    });
}
exports.redirectToLogin = redirectToLogin;
function generateDataContext(widget) {
    const dataContext = {};
    while (widget === null || widget === void 0 ? void 0 : widget._scope) {
        const current = widget;
        // 此处采用代理的方式，是为了可以获取到最新的 _scope.dataContext 防止 dataContext 引用被重新赋值
        Object.defineProperty(dataContext, current._scope.id, {
            get() {
                return current._scope.dataContext;
            },
        });
        widget = widget.parent;
    }
    return dataContext;
}
exports.generateDataContext = generateDataContext;
exports.ENABLE_OBSERVER_REF = false;
function setEnableObserverRef(value) {
    exports.ENABLE_OBSERVER_REF = value;
}
exports.setEnableObserverRef = setEnableObserverRef;
exports.ENABLE_PAGE_ROOT_ID = false;
function setEnablePageRoot(value) {
    exports.ENABLE_PAGE_ROOT_ID = value;
}
exports.setEnablePageRoot = setEnablePageRoot;
exports.ENABLE_WECOM = false;
function setEnableWecom(value) {
    exports.ENABLE_WECOM = value;
}
exports.setEnableWecom = setEnableWecom;
/**
 * 是否开启原地企微登录
 * 1. 针对单环境白名单
 * 2. 在企微环境打开
 * 3. 自定义应用（即：非企业工作台)
 */
const WECOM_ENVID_LIST = [
    'lowcode-4gzdsu5k66946492',
    'lowcode-2gay8jgh25c7b1cf',
    'lowcode-4g9b78bx94404d85',
    'lowcode-8gmx7bat3135e2de',
];
function isEnableWecom(envId) {
    const adminPortal = simpleCheckAdminPortal();
    if ((0, helper_1.inWxWork)() && !adminPortal && WECOM_ENVID_LIST.includes(envId)) {
        return true;
    }
}
exports.isEnableWecom = isEnableWecom;
function serde(a) {
    return JSON.parse(JSON.stringify(a));
}
exports.serde = serde;
const isObj = (a) => typeof a === 'object' && a !== null;
function isEqual(a, b, shouldSerde = false) {
    if (shouldSerde && isObj(a) && isObj(b)) {
        // for Proxy created by mbox
        return (0, lodash_es_1.isEqual)(serde(a), serde(b));
    }
    return (0, lodash_es_1.isEqual)(a, b);
}
exports.isEqual = isEqual;
const _REPORTED = {};
function reportTime(tag, time, only = false) {
    var _a, _b, _c;
    const excludes = ['app-nvzcvt10', 'app-msa2ihs9'];
    const wedahostconfig = window._WedaHostConfig;
    if (!window._aegis || !tag || simpleCheckAdminPortal() || !window._aegis_inited || excludes.includes(global_api_1.app.id)) {
        return;
    }
    if (wedahostconfig && !wedahostconfig._REPORTED) {
        wedahostconfig._REPORTED = _REPORTED;
    }
    const CACHE_MAP = (wedahostconfig === null || wedahostconfig === void 0 ? void 0 : wedahostconfig._REPORTED) || _REPORTED;
    if (only && CACHE_MAP[tag]) {
        return;
    }
    CACHE_MAP[tag] = true;
    const { envVersion } = ((_b = (_a = global_api_1.app.__internal__) === null || _a === void 0 ? void 0 : _a.getConfig) === null || _b === void 0 ? void 0 : _b.call(_a)) || {};
    try {
        let t = time === undefined ? ((_c = performance === null || performance === void 0 ? void 0 : performance.now) === null || _c === void 0 ? void 0 : _c.call(performance)) || Date.now() - window._aegis_inited : time;
        window._aegis.reportTime({
            name: tag,
            duration: t,
            ext2: envVersion,
        });
        if (t > 5000 && (performance === null || performance === void 0 ? void 0 : performance.getEntries)) {
            window._aegis.report({
                msg: performance.getEntries(),
                ext2: envVersion,
                trace: 'trace',
            });
        }
    }
    catch (e) { }
}
exports.reportTime = reportTime;
function reportEvent(tag) {
    var _a, _b, _c, _d;
    const { envVersion } = ((_b = (_a = global_api_1.app.__internal__) === null || _a === void 0 ? void 0 : _a.getConfig) === null || _b === void 0 ? void 0 : _b.call(_a)) || {};
    try {
        // console.log('>>>>>>reportevent:', tag);
        (_d = (_c = window._aegis) === null || _c === void 0 ? void 0 : _c.reportEvent) === null || _d === void 0 ? void 0 : _d.call(_c, {
            name: tag,
            ext2: envVersion,
        });
    }
    catch (e) { }
}
exports.reportEvent = reportEvent;
function commonReport(message) {
    var _a, _b, _c, _d;
    const { envVersion } = ((_b = (_a = global_api_1.app.__internal__) === null || _a === void 0 ? void 0 : _a.getConfig) === null || _b === void 0 ? void 0 : _b.call(_a)) || {};
    try {
        (_d = (_c = window._aegis) === null || _c === void 0 ? void 0 : _c.report) === null || _d === void 0 ? void 0 : _d.call(_c, {
            msg: message,
            ext2: envVersion,
        });
    }
    catch (e) { }
}
exports.commonReport = commonReport;
function simpleCheckAdminPortal() {
    return window._WedaHostConfig && window.__POWERED_BY_QIANKUN__;
}
exports.simpleCheckAdminPortal = simpleCheckAdminPortal;
function getNetworkType(window) {
    var _a, _b, _c, _d, _e, _f, _g;
    const ua = ((_a = window === null || window === void 0 ? void 0 : window.navigator) === null || _a === void 0 ? void 0 : _a.userAgent) || '';
    let networkTypeStr = ua.match(/NetType\/\w+/)
        ? (_d = (_c = (_b = ua
            .match(/NetType\/\w+/)) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.toLowerCase()) === null || _d === void 0 ? void 0 : _d.replace('nettype/', '')
        : ((_g = (_f = (_e = window === null || window === void 0 ? void 0 : window.navigator) === null || _e === void 0 ? void 0 : _e.connection) === null || _f === void 0 ? void 0 : _f.effectiveType) === null || _g === void 0 ? void 0 : _g.toLowerCase()) || '';
    const types = ['2g', '3g', '4g', '5g', 'wifi'];
    for (const type of types) {
        if (networkTypeStr.includes(type))
            return type;
    }
    return networkTypeStr ? 'other' : '';
}
exports.getNetworkType = getNetworkType;
//# sourceMappingURL=common.js.map