"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __awaiter = (this && this.__awaiter) || function (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());
    });
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TUIStore = exports.TUIGlobal = void 0;
const tui_core_1 = require("@tencentcloud/tui-core");
const index_1 = require("../const/index");
// @ts-ignore
const tuicall_engine_wx_1 = require("tuicall-engine-wx");
const index_2 = require("../locales/index");
const miniProgram_1 = require("./miniProgram");
const bellContext_1 = require("./bellContext");
const index_3 = require("../utils/validate/index");
const common_utils_1 = require("../utils/common-utils");
const utils_1 = require("./utils");
const timer_1 = __importDefault(require("../utils/timer"));
const tuiGlobal_1 = __importDefault(require("../TUIGlobal/tuiGlobal"));
const tuiStore_1 = __importDefault(require("../TUIStore/tuiStore"));
const TUIGlobal = tuiGlobal_1.default.getInstance();
exports.TUIGlobal = TUIGlobal;
const TUIStore = tuiStore_1.default.getInstance();
exports.TUIStore = TUIStore;
const version = '2.1.1';
class TUICallService {
    constructor() {
        this._tim = null;
        this._TUICore = null;
        this._timerId = -1;
        this._startTimeStamp = (0, common_utils_1.performanceNow)();
        this._bellContext = null;
        this._defaultOfflinePushInfo = {
            title: '',
            description: (0, index_2.t)('you have a new call'),
        };
        // =========================【监听 TUIStore 中的状态】=========================
        this._handleCallStatusChange = (value) => __awaiter(this, void 0, void 0, function* () {
            var _a, _b;
            try {
                const bellParams = {
                    callRole: TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_ROLE),
                    callStatus: TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_STATUS),
                };
                this._bellContext.setBellProperties(bellParams);
                if (value === index_1.CallStatus.CALLING) {
                    yield ((_a = this === null || this === void 0 ? void 0 : this._bellContext) === null || _a === void 0 ? void 0 : _a.play());
                }
                else {
                    // 状态变更通知
                    if (value === index_1.CallStatus.CONNECTED) {
                        const isGroup = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.IS_GROUP);
                        const callMediaType = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_MEDIA_TYPE);
                        const remoteUserInfoList = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST);
                        const oldStatus = isGroup ? index_1.StatusChange.DIALING_GROUP : index_1.StatusChange.DIALING_C2C;
                        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.CALL_TIPS, '');
                        this.statusChanged && this.statusChanged({ oldStatus, newStatus: (0, utils_1.generateStatusChangeText)(TUIStore) });
                        if (!isGroup && callMediaType === index_1.CallMediaType.VIDEO) {
                            this.switchScreen(remoteUserInfoList[0].domId);
                        }
                    }
                    yield ((_b = this === null || this === void 0 ? void 0 : this._bellContext) === null || _b === void 0 ? void 0 : _b.stop());
                }
            }
            catch (error) {
                console.warn(`${index_1.NAME.PREFIX}handleCallStatusChange, ${error}.`);
            }
        });
        console.log(`${index_1.NAME.PREFIX}version: ${version}`);
        this._watchTUIStore();
        this._bellContext = new bellContext_1.BellContext();
        // 下面：TUICore注册事件，注册组件服务，注册界面拓展
        tui_core_1.TUICore.registerEvent(tui_core_1.TUIConstants.TUILogin.EVENT.LOGIN_STATE_CHANGED, tui_core_1.TUIConstants.TUILogin.EVENT_SUB_KEY.USER_LOGIN_SUCCESS, this);
        tui_core_1.TUICore.registerService(tui_core_1.TUIConstants.TUICalling.SERVICE.NAME, this);
        tui_core_1.TUICore.registerExtension(tui_core_1.TUIConstants.TUIChat.EXTENSION.INPUT_MORE.EXT_ID, this);
    }
    static getInstance() {
        if (!TUICallService.instance) {
            TUICallService.instance = new TUICallService();
        }
        return TUICallService.instance;
    }
    init(params) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                if (this._tuiCallEngine)
                    return;
                // @ts-ignore
                let { userID, tim, userSig, sdkAppID, SDKAppID, isFromChat } = params;
                if (this._TUICore) {
                    sdkAppID = this._TUICore.SDKAppID;
                    tim = this._TUICore.tim;
                }
                this._tim = tim;
                console.log(`${index_1.NAME.PREFIX}init sdkAppId: ${sdkAppID || SDKAppID}, userId: ${userID}`);
                this._tuiCallEngine = tuicall_engine_wx_1.TUICallEngine.createInstance({
                    tim,
                    // @ts-ignore
                    sdkAppID: sdkAppID || SDKAppID,
                    callkitVersion: version,
                    chat: isFromChat || false,
                });
                this._addListenTuiCallEngineEvent();
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO, { userId: userID });
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN, { userId: userID });
                yield this._tuiCallEngine.login({ userID, userSig, assetsPath: '' }); // web && mini
            }
            catch (error) {
                console.error(`${index_1.NAME.PREFIX}init failed, error: ${error}.`);
                throw error;
            }
        });
    }
    // component destroy
    destroyed() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const currentCallStatus = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_STATUS);
                if (currentCallStatus !== index_1.CallStatus.IDLE) {
                    throw new Error(`please destroyed when status is idle, current status: ${currentCallStatus}`);
                }
                if (this._tuiCallEngine) {
                    this._removeListenTuiCallEngineEvent();
                    yield this._tuiCallEngine.destroyInstance();
                    this._tuiCallEngine = null;
                }
            }
            catch (error) {
                console.error(`${index_1.NAME.PREFIX}destroyed failed, error: ${error}.`);
                throw error;
            }
        });
    }
    // ===============================【通话操作】===============================
    call(callParams) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const { type, userID, offlinePushInfo } = callParams;
                if (TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_STATUS) !== index_1.CallStatus.IDLE)
                    return;
                yield this._updateCallStoreBeforeCall(type, [{ userId: userID }]);
                this._executeExternalBeforeCalling(); // 执行外部传入的 beforeCall 方法
                callParams.offlinePushInfo = Object.assign(Object.assign({}, this._defaultOfflinePushInfo), offlinePushInfo);
                const response = yield this._tuiCallEngine.call(callParams);
                yield this._updateCallStoreAfterCall([userID], response);
            }
            catch (error) {
                this._handleCallError(error, 'call');
            }
        });
    }
    ;
    groupCall(groupCallParams) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const { userIDList, type, groupID, offlinePushInfo } = groupCallParams;
                if (TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_STATUS) !== index_1.CallStatus.IDLE)
                    return;
                const remoteUserInfoList = userIDList.map(userId => ({ userId }));
                yield this._updateCallStoreBeforeCall(type, remoteUserInfoList, groupID);
                this._executeExternalBeforeCalling();
                groupCallParams.offlinePushInfo = Object.assign(Object.assign({}, this._defaultOfflinePushInfo), offlinePushInfo);
                const response = yield this._tuiCallEngine.groupCall(groupCallParams);
                yield this._updateCallStoreAfterCall(userIDList, response);
            }
            catch (error) {
                this._handleCallError(error, 'groupCall');
            }
        });
    }
    inviteUser(params) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const { userIDList } = params;
                let inviteUserInfoList = yield (0, utils_1.getRemoteUserProfile)(userIDList, this.getTim(), TUIStore);
                const remoteUserInfoList = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST);
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST, [...remoteUserInfoList, ...inviteUserInfoList]);
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_EXCLUDE_VOLUMN_LIST, [...remoteUserInfoList, ...inviteUserInfoList]);
                this._tuiCallEngine && (yield this._tuiCallEngine.inviteUser(params));
            }
            catch (error) {
                console.error(`${index_1.NAME.PREFIX}inviteUser failed, error: ${error}.`);
                this._resetCallStore();
                throw error;
            }
        });
    }
    joinInGroupCall(params) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const updateStoreParams = {
                    [index_1.NAME.CALL_ROLE]: index_1.CallRole.CALLEE,
                    [index_1.NAME.IS_GROUP]: true,
                    [index_1.NAME.CALL_STATUS]: index_1.CallStatus.CONNECTED,
                    [index_1.NAME.CALL_MEDIA_TYPE]: params.type,
                    [index_1.NAME.GROUP_ID]: params.groupID,
                    [index_1.NAME.ROOM_ID]: params.roomID,
                };
                TUIStore.updateStore(updateStoreParams, index_1.StoreName.CALL);
                const response = yield this._tuiCallEngine.joinInGroupCall(params);
                (params.type === index_1.CallMediaType.VIDEO) && (yield this.openCamera(index_1.NAME.LOCAL_VIDEO));
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.IS_CLICKABLE, true);
                this._startTimer();
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.PUSHER, response);
                this.setSoundMode(params.type === index_1.CallMediaType.AUDIO ? index_1.AudioPlayBackDevice.EAR : index_1.AudioPlayBackDevice.SPEAKER);
                const localUserInfo = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO);
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO, Object.assign(Object.assign({}, localUserInfo), { isEnter: true }));
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN, Object.assign(Object.assign({}, localUserInfo), { isEnter: true }));
                this._setLocalUserInfoAudioVideoAvailable(true, index_1.NAME.AUDIO);
            }
            catch (error) {
                console.error(`${index_1.NAME.PREFIX}joinInGroupCall failed, error: ${error}.`);
                this._resetCallStore();
                throw error;
            }
        });
    }
    // ===============================【其它对外接口】===============================
    getTUICallEngineInstance() {
        return (this === null || this === void 0 ? void 0 : this._tuiCallEngine) || null;
    }
    setLogLevel(level) {
        var _a;
        (_a = this === null || this === void 0 ? void 0 : this._tuiCallEngine) === null || _a === void 0 ? void 0 : _a.setLogLevel(level);
    }
    setLanguage(language) {
        if (language && Object.values(index_1.LanguageType).includes(language)) {
            TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LANGUAGE, language);
        }
    }
    enableFloatWindow(enable) {
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.ENABLE_FLOAT_WINDOW, enable);
    }
    setSelfInfo(params) {
        return __awaiter(this, void 0, void 0, function* () {
            const { nickName, avatar } = params;
            try {
                yield this._tuiCallEngine.setSelfInfo(nickName, avatar);
            }
            catch (error) {
                console.error(`${index_1.NAME.PREFIX}setSelfInfo failed, error: ${error}.`);
            }
        });
    }
    // 修改默认铃声：只支持本地铃声文件，不支持在线铃声文件；修改铃声修改的是被叫的铃声
    setCallingBell(filePath) {
        return __awaiter(this, void 0, void 0, function* () {
            let isCheckFileExist = true;
            if (!isCheckFileExist) {
                console.warn(`${index_1.NAME.PREFIX}setCallingBell failed, filePath: ${filePath}.`);
                return;
            }
            const bellParams = { calleeBellFilePath: filePath };
            this._bellContext.setBellProperties(bellParams);
        });
    }
    enableMuteMode(enable) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const bellParams = { isMuteBell: enable };
                this._bellContext.setBellProperties(bellParams);
                yield this._bellContext.setBellMute(enable);
            }
            catch (error) {
                console.warn(`${index_1.NAME.PREFIX}enableMuteMode failed, error: ${error}.`);
            }
        });
    }
    // =============================【内部按钮操作方法】=============================
    accept() {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const response = yield this._tuiCallEngine.accept();
                if (response) {
                    // 小程序接通时会进行授权弹框, 状态需要放在 accept 后, 否则先接通后再拉起权限设置
                    TUIStore.update(index_1.StoreName.CALL, index_1.NAME.CALL_STATUS, index_1.CallStatus.CONNECTED);
                    this._callTUIService({ message: (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.message });
                    TUIStore.update(index_1.StoreName.CALL, index_1.NAME.IS_CLICKABLE, true);
                    this._startTimer();
                    const callMediaType = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_MEDIA_TYPE);
                    (callMediaType === index_1.CallMediaType.VIDEO) && (yield this.openCamera(index_1.NAME.LOCAL_VIDEO));
                    response.pusher && TUIStore.update(index_1.StoreName.CALL, index_1.NAME.PUSHER, response.pusher);
                    this.setSoundMode(callMediaType === index_1.CallMediaType.AUDIO ? index_1.AudioPlayBackDevice.EAR : index_1.AudioPlayBackDevice.SPEAKER);
                    const localUserInfo = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO);
                    TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO, Object.assign(Object.assign({}, localUserInfo), { isEnter: true }));
                    TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN, Object.assign(Object.assign({}, localUserInfo), { isEnter: true }));
                    this._setLocalUserInfoAudioVideoAvailable(true, index_1.NAME.AUDIO); // web && mini default open audio
                }
            }
            catch (error) {
                if ((0, common_utils_1.handleRepeatedCallError)(error))
                    return;
                this._noDevicePermissionToast(error, index_1.CallMediaType.AUDIO);
                this._resetCallStore();
            }
        });
    }
    hangup() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const response = yield this._tuiCallEngine.hangup();
                response === null || response === void 0 ? void 0 : response.forEach((item) => {
                    var _a;
                    if ((item === null || item === void 0 ? void 0 : item.code) === 0) {
                        this._callTUIService({ message: (_a = item === null || item === void 0 ? void 0 : item.data) === null || _a === void 0 ? void 0 : _a.message });
                    }
                });
            }
            catch (error) {
                console.debug(error);
            }
            this._resetCallStore();
        });
    }
    reject() {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const response = yield this._tuiCallEngine.reject();
                if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
                    this._callTUIService({ message: (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.message });
                }
            }
            catch (error) {
                console.debug(error);
            }
            this._resetCallStore();
        });
    }
    openCamera(videoViewDomID) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                yield this._tuiCallEngine.openCamera();
                this._setLocalUserInfoAudioVideoAvailable(true, index_1.NAME.VIDEO);
            }
            catch (error) {
                this._noDevicePermissionToast(error, index_1.CallMediaType.VIDEO);
                console.error(`${index_1.NAME.PREFIX}openCamera error: ${error}.`);
            }
        });
    }
    closeCamera() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                yield this._tuiCallEngine.closeCamera();
                this._setLocalUserInfoAudioVideoAvailable(false, index_1.NAME.VIDEO);
            }
            catch (error) {
                console.error(`${index_1.NAME.PREFIX}closeCamera error: ${error}.`);
            }
        });
    }
    openMicrophone() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                yield this._tuiCallEngine.openMicrophone();
                this._setLocalUserInfoAudioVideoAvailable(true, index_1.NAME.AUDIO);
            }
            catch (error) {
                console.error(`${index_1.NAME.PREFIX}openMicrophone failed, error: ${error}.`);
            }
        });
    }
    closeMicrophone() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                yield this._tuiCallEngine.closeMicrophone();
                this._setLocalUserInfoAudioVideoAvailable(false, index_1.NAME.AUDIO);
            }
            catch (error) {
                console.error(`${index_1.NAME.PREFIX}closeMicrophone failed, error: ${error}.`);
            }
        });
    }
    switchScreen(userId) {
        if (!userId)
            return;
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.BIG_SCREEN_USER_ID, userId);
    }
    // support video to audio; not support audio to video
    switchCallMediaType() {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const callMediaType = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_MEDIA_TYPE);
                if (callMediaType === index_1.CallMediaType.AUDIO) {
                    console.warn(`${index_1.NAME.PREFIX}switchCallMediaType failed, ${callMediaType} not support.`);
                    return;
                }
                const response = yield this._tuiCallEngine.switchCallMediaType(index_1.CallMediaType.AUDIO);
                if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
                    this._callTUIService({ message: (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.message });
                }
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.CALL_MEDIA_TYPE, index_1.CallMediaType.AUDIO);
                const isGroup = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.IS_GROUP);
                const oldStatus = isGroup ? index_1.StatusChange.CALLING_GROUP_VIDEO : index_1.StatusChange.CALLING_C2C_VIDEO;
                const newStatus = (0, utils_1.generateStatusChangeText)(TUIStore);
                this.statusChanged && this.statusChanged({ oldStatus, newStatus });
                this.setSoundMode(index_1.AudioPlayBackDevice.EAR);
            }
            catch (error) {
                console.error(`${index_1.NAME.PREFIX}switchCallMediaType failed, error: ${error}.`);
            }
        });
    }
    switchCamera() {
        return __awaiter(this, void 0, void 0, function* () {
            const currentPosition = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CAMERA_POSITION);
            const targetPosition = currentPosition === index_1.CameraPosition.BACK ? index_1.CameraPosition.FRONT : index_1.CameraPosition.BACK;
            try {
                yield this._tuiCallEngine.switchCamera(targetPosition);
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.CAMERA_POSITION, targetPosition);
            }
            catch (error) {
                console.error(`${index_1.NAME.PREFIX}_switchCamera failed, error: ${error}.`);
            }
        });
    }
    setSoundMode(type) {
        var _a;
        try {
            let isEarPhone = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.IS_EAR_PHONE);
            const soundMode = type || (isEarPhone ? index_1.AudioPlayBackDevice.SPEAKER : index_1.AudioPlayBackDevice.EAR); // UI 层切换时传参数
            (_a = this._tuiCallEngine) === null || _a === void 0 ? void 0 : _a.selectAudioPlaybackDevice(soundMode);
            if (type) {
                isEarPhone = type === index_1.AudioPlayBackDevice.EAR;
            }
            else {
                isEarPhone = !isEarPhone;
            }
            TUIStore.update(index_1.StoreName.CALL, index_1.NAME.IS_EAR_PHONE, isEarPhone);
        }
        catch (error) {
            console.error(`${index_1.NAME.PREFIX}setSoundMode failed, error: ${error}.`);
        }
    }
    // 切前后置 miniProgram, 切扬声器
    getTim() {
        var _a, _b;
        if (this._tim)
            return this._tim;
        if (!this._tuiCallEngine) {
            console.warn(`${index_1.NAME.PREFIX}getTim warning: _tuiCallEngine Instance is not available.`);
            return null;
        }
        return ((_a = this._tuiCallEngine) === null || _a === void 0 ? void 0 : _a.tim) || ((_b = this._tuiCallEngine) === null || _b === void 0 ? void 0 : _b.getTim()); // mini support getTim interface
    }
    // ==========================【TUICallEngine 事件处理】==========================
    _addListenTuiCallEngineEvent() {
        if (!this._tuiCallEngine) {
            console.warn(`${index_1.NAME.PREFIX}add engine event listener failed, engine is empty.`);
            return;
        }
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.ERROR, this._handleError, this);
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.INVITED, this._handleNewInvitationReceived, this); // 收到邀请事件
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.USER_ACCEPT, this._handleUserAccept, this); // 主叫收到被叫接通事件
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.USER_ENTER, this._handleUserEnter, this); // 有用户进房事件
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.USER_LEAVE, this._handleUserLeave, this); // 有用户离开通话事件
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.REJECT, this._handleInviteeReject, this); // 主叫收到被叫的拒绝通话事件
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.NO_RESP, this._handleNoResponse, this); // 主叫收到被叫的无应答事件
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.LINE_BUSY, this._handleLineBusy, this); // 主叫收到被叫的忙线事件
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.CALLING_CANCEL, this._handleCallingCancel, this); // 主被叫在通话未建立时, 收到的取消事件
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.SDK_READY, this._handleSDKReady, this); // SDK Ready 回调
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.KICKED_OUT, this._handleKickedOut, this); // 未开启多端登录时, 多端登录收到的被踢事件
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.MESSAGE_SENT_BY_ME, this._messageSentByMe, this);
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.CALL_END, this._handleCallingEnd, this); // 主被叫在通话结束时, 收到的通话结束事件
        // @ts-ignore
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.CALL_MODE, this._handleCallTypeChange, this);
        // @ts-ignore
        this._tuiCallEngine.on(tuicall_engine_wx_1.EVENT.USER_UPDATE, this._handleUserUpdate, this); // mini: user data update
    }
    _removeListenTuiCallEngineEvent() {
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.ERROR, this._handleError);
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.INVITED, this._handleNewInvitationReceived);
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.USER_ACCEPT, this._handleUserAccept);
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.USER_ENTER, this._handleUserEnter);
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.USER_LEAVE, this._handleUserLeave);
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.REJECT, this._handleInviteeReject);
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.NO_RESP, this._handleNoResponse);
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.LINE_BUSY, this._handleLineBusy);
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.CALLING_CANCEL, this._handleCallingCancel);
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.SDK_READY, this._handleSDKReady);
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.KICKED_OUT, this._handleKickedOut);
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.MESSAGE_SENT_BY_ME, this._messageSentByMe);
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.CALL_END, this._handleCallingEnd);
        // @ts-ignore
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.CALL_MODE, this._handleCallTypeChange); // 切换通话事件 miniProgram CALL_MODE
        // @ts-ignore
        this._tuiCallEngine.off(tuicall_engine_wx_1.EVENT.USER_UPDATE, this._handleUserUpdate); // mini: user data update
    }
    _handleError(event) {
        const { code, message } = event || {};
        const index = Object.values(index_1.ErrorCode).indexOf(code);
        let callTips = '';
        if (index !== -1) {
            const key = Object.keys(index_1.ErrorCode)[index];
            callTips = (0, index_2.t)(index_1.ErrorMessage[key]);
            callTips && TUIStore.update(index_1.StoreName.CALL, index_1.NAME.TOAST_INFO, { text: callTips, type: index_1.NAME.ERROR });
        }
        this._executeExternalAfterCalling();
        console.error(`${index_1.NAME.PREFIX}_handleError, errorCode: ${code}; errorMessage: ${callTips || message}.`);
    }
    _handleNewInvitationReceived(event) {
        return __awaiter(this, void 0, void 0, function* () {
            console.log(`${index_1.NAME.PREFIX}onCallReceived event data: ${JSON.stringify(event)}.`);
            const { sponsor = '', isFromGroup, callMediaType, inviteData = {}, calleeIdList = [], groupID = '' } = this._analyzeEventData(event);
            const currentUserInfo = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO);
            const remoteUserIdList = [sponsor, ...calleeIdList.filter((userId) => userId !== currentUserInfo.userId)];
            const type = callMediaType || inviteData.callType;
            const callTipsKey = type === index_1.CallMediaType.AUDIO ? index_2.CallTips.CALLEE_CALLING_AUDIO_MSG : index_2.CallTips.CALLEE_CALLING_VIDEO_MSG;
            let updateStoreParams = {
                [index_1.NAME.CALL_ROLE]: index_1.CallRole.CALLEE,
                [index_1.NAME.IS_GROUP]: isFromGroup,
                [index_1.NAME.CALL_STATUS]: index_1.CallStatus.CALLING,
                [index_1.NAME.CALL_MEDIA_TYPE]: type,
                [index_1.NAME.CALL_TIPS]: (0, index_2.t)(callTipsKey),
                [index_1.NAME.CALLER_USER_INFO]: { userId: sponsor },
                [index_1.NAME.GROUP_ID]: groupID,
            };
            (0, miniProgram_1.initAndCheckRunEnv)();
            const pusher = { enableCamera: type === index_1.CallMediaType.VIDEO, enableMic: true }; // mini 默认打开麦克风
            updateStoreParams = Object.assign(Object.assign({}, updateStoreParams), { [index_1.NAME.PUSHER]: pusher });
            TUIStore.updateStore(updateStoreParams, index_1.StoreName.CALL);
            this._executeExternalBeforeCalling();
            this.statusChanged && this.statusChanged({ oldStatus: index_1.StatusChange.IDLE, newStatus: index_1.StatusChange.BE_INVITED });
            const remoteUserInfoList = yield (0, utils_1.getRemoteUserProfile)(remoteUserIdList, this.getTim(), TUIStore);
            const [userInfo] = remoteUserInfoList.filter((userInfo) => userInfo.userId === sponsor);
            remoteUserInfoList.length > 0 && TUIStore.updateStore({
                [index_1.NAME.REMOTE_USER_INFO_LIST]: remoteUserInfoList,
                [index_1.NAME.REMOTE_USER_INFO_EXCLUDE_VOLUMN_LIST]: remoteUserInfoList,
                [index_1.NAME.CALLER_USER_INFO]: {
                    userId: sponsor,
                    nick: (userInfo === null || userInfo === void 0 ? void 0 : userInfo.nick) || '',
                    avatar: (userInfo === null || userInfo === void 0 ? void 0 : userInfo.avatar) || '',
                    displayUserInfo: (userInfo === null || userInfo === void 0 ? void 0 : userInfo.remark) || (userInfo === null || userInfo === void 0 ? void 0 : userInfo.nick) || sponsor,
                },
            }, index_1.StoreName.CALL);
        });
    }
    _handleUserAccept(event) {
        this._callerChangeToConnected();
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.TOAST_INFO, (0, index_2.t)('answered'));
        console.log(`${index_1.NAME.PREFIX}accept event data: ${JSON.stringify(event)}.`);
    }
    _handleUserEnter(event) {
        return __awaiter(this, void 0, void 0, function* () {
            this._callerChangeToConnected();
            const { userID: userId, data } = this._analyzeEventData(event);
            (data === null || data === void 0 ? void 0 : data.playerList) && TUIStore.update(index_1.StoreName.CALL, index_1.NAME.PLAYER, data.playerList);
            let remoteUserInfoList = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST);
            const isInRemoteUserList = remoteUserInfoList.find(item => (item === null || item === void 0 ? void 0 : item.userId) === userId);
            if (!isInRemoteUserList) {
                remoteUserInfoList.push({ userId });
                if (remoteUserInfoList.length > 0) {
                    TUIStore.update(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST, remoteUserInfoList);
                    TUIStore.update(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_EXCLUDE_VOLUMN_LIST, remoteUserInfoList);
                }
                const [userInfo] = yield (0, utils_1.getRemoteUserProfile)([userId], this.getTim(), TUIStore);
                remoteUserInfoList = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST);
                remoteUserInfoList.forEach((obj) => {
                    if ((obj === null || obj === void 0 ? void 0 : obj.userId) === userId) {
                        obj = Object.assign(obj, userInfo);
                    }
                });
            }
            remoteUserInfoList = remoteUserInfoList.map((obj) => {
                if (obj.userId === userId)
                    obj.isEnter = true;
                return obj;
            });
            if (remoteUserInfoList.length > 0) {
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST, remoteUserInfoList);
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_EXCLUDE_VOLUMN_LIST, remoteUserInfoList);
            }
            console.log(`${index_1.NAME.PREFIX}userEnter event data: ${JSON.stringify(event)}.`);
        });
    }
    _callerChangeToConnected() {
        const callRole = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_ROLE);
        const callStatus = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_STATUS);
        if (callStatus === index_1.CallStatus.CALLING && callRole === index_1.CallRole.CALLER) {
            TUIStore.update(index_1.StoreName.CALL, index_1.NAME.CALL_STATUS, index_1.CallStatus.CONNECTED);
            this._startTimer();
        }
    }
    _handleUserLeave(event) {
        console.log(`${index_1.NAME.PREFIX}userLeave event data: ${JSON.stringify(event)}.`);
        const { data, userID: userId } = this._analyzeEventData(event);
        (data === null || data === void 0 ? void 0 : data.playerList) && TUIStore.update(index_1.StoreName.CALL, index_1.NAME.PLAYER, data.playerList);
        if (TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.IS_GROUP)) {
            const remoteUserInfoList = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST);
            const prefix = (remoteUserInfoList.find(obj => obj.userId === userId) || {}).displayUserInfo || userId;
            const text = (0, utils_1.generateText)(TUIStore, index_2.CallTips.END_CALL, prefix);
            TUIStore.update(index_1.StoreName.CALL, index_1.NAME.TOAST_INFO, { text });
        }
        userId && this._deleteRemoteUser([userId]);
    }
    _unNormalEventsManager(event, eventName) {
        console.log(`${index_1.NAME.PREFIX}${eventName} event data: ${JSON.stringify(event)}.`);
        const isGroup = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.IS_GROUP);
        const remoteUserInfoList = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST);
        switch (eventName) {
            case tuicall_engine_wx_1.EVENT.REJECT:
            case tuicall_engine_wx_1.EVENT.LINE_BUSY: {
                const { userID: userId } = this._analyzeEventData(event);
                let callTipsKey = eventName === tuicall_engine_wx_1.EVENT.REJECT ? index_2.CallTips.OTHER_SIDE_REJECT_CALL : index_2.CallTips.OTHER_SIDE_LINE_BUSY;
                let text = (0, utils_1.generateText)(TUIStore, callTipsKey);
                if (isGroup) {
                    const prefix = (remoteUserInfoList.find(obj => obj.userId === userId) || {}).displayUserInfo || userId;
                    callTipsKey = eventName === tuicall_engine_wx_1.EVENT.REJECT ? index_2.CallTips.REJECT_CALL : index_2.CallTips.IN_BUSY;
                    text = (0, utils_1.generateText)(TUIStore, callTipsKey, prefix);
                }
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.TOAST_INFO, { text });
                userId && this._deleteRemoteUser([userId]);
                break;
            }
            case tuicall_engine_wx_1.EVENT.NO_RESP: {
                const { userIDList = [] } = this._analyzeEventData(event);
                const callTipsKey = isGroup ? index_2.CallTips.TIMEOUT : index_2.CallTips.CALL_TIMEOUT;
                const userInfoList = userIDList.map(userId => {
                    const userInfo = remoteUserInfoList.find(obj => obj.userId === userId) || {};
                    return userInfo.displayUserInfo || userId;
                });
                const text = isGroup ? (0, utils_1.generateText)(TUIStore, callTipsKey, userInfoList.join()) : (0, utils_1.generateText)(TUIStore, callTipsKey);
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.TOAST_INFO, { text });
                userIDList.length > 0 && this._deleteRemoteUser(userIDList);
                break;
            }
            case tuicall_engine_wx_1.EVENT.CALLING_CANCEL: {
                // TUIStore.update(StoreName.CALL, NAME.TOAST_INFO, { text: generateText(TUIStore, CallTips.CANCEL) });
                this._resetCallStore();
                break;
            }
        }
    }
    _handleInviteeReject(event) {
        this._unNormalEventsManager(event, tuicall_engine_wx_1.EVENT.REJECT);
    }
    _handleNoResponse(event) {
        this._unNormalEventsManager(event, tuicall_engine_wx_1.EVENT.NO_RESP);
    }
    _handleLineBusy(event) {
        this._unNormalEventsManager(event, tuicall_engine_wx_1.EVENT.LINE_BUSY);
    }
    _handleCallingCancel(event) {
        this._executeExternalAfterCalling();
        this._unNormalEventsManager(event, tuicall_engine_wx_1.EVENT.CALLING_CANCEL);
    }
    _handleCallingEnd(event) {
        console.log(`${index_1.NAME.PREFIX}callEnd event data: ${JSON.stringify(event)}.`);
        this._executeExternalAfterCalling();
        this._resetCallStore();
    }
    // SDK_READY 后才能调用 tim 接口, 否则登录后立刻获取导致调用接口失败. v2.27.4+、v3 接口 login 后会抛出 SDK_READY
    _handleSDKReady(event) {
        return __awaiter(this, void 0, void 0, function* () {
            let localUserInfo = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO);
            localUserInfo = yield (0, utils_1.getMyProfile)(localUserInfo.userId, this.getTim(), TUIStore);
            this._defaultOfflinePushInfo.title = localUserInfo === null || localUserInfo === void 0 ? void 0 : localUserInfo.displayUserInfo;
            TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO, localUserInfo);
            TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN, localUserInfo);
        });
    }
    _handleKickedOut(event) {
        console.log(`${index_1.NAME.PREFIX}kickOut event data: ${JSON.stringify(event)}.`);
        this.kickedOut && this.kickedOut(event);
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.CALL_TIPS, (0, utils_1.generateText)(TUIStore, index_2.CallTips.KICK_OUT));
        this._resetCallStore();
    }
    _handleCallTypeChange(event) {
        const { newCallType, type } = this._analyzeEventData(event);
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.CALL_MEDIA_TYPE, newCallType || type);
        this.setSoundMode(index_1.AudioPlayBackDevice.EAR);
    }
    _messageSentByMe(event) {
        const message = event === null || event === void 0 ? void 0 : event.data;
        this.onMessageSentByMe && this.onMessageSentByMe(message);
    }
    // ==========================【 miniProgram 私有事件】==========================
    _handleUserUpdate(event) {
        const data = this._analyzeEventData(event);
        (data === null || data === void 0 ? void 0 : data.pusher) && TUIStore.update(index_1.StoreName.CALL, index_1.NAME.PUSHER, data.pusher);
        (data === null || data === void 0 ? void 0 : data.playerList) && TUIStore.update(index_1.StoreName.CALL, index_1.NAME.PLAYER, data.playerList);
    }
    // 处理 “呼叫” 抛出的异常
    _handleCallError(error, methodName) {
        if ((0, common_utils_1.handleRepeatedCallError)(error))
            return;
        (0, miniProgram_1.handlePackageError)(error); // 无套餐提示, 小程序 engine 不抛出 onError
        this._noDevicePermissionToast(error, index_1.CallMediaType.AUDIO);
        console.error(`${index_1.NAME.PREFIX}${methodName} failed, error: ${error}.`);
        this._resetCallStore();
        throw error;
    }
    setCallback(params) {
        const { beforeCalling, afterCalling, onMinimized, onMessageSentByMe, kickedOut, statusChanged } = params;
        beforeCalling && (this.beforeCalling = beforeCalling);
        afterCalling && (this.afterCalling = afterCalling);
        onMinimized && (this.onMinimized = onMinimized);
        onMessageSentByMe && (this.onMessageSentByMe = onMessageSentByMe);
        kickedOut && (this.kickedOut = kickedOut);
        statusChanged && (this.statusChanged = statusChanged);
    }
    toggleMinimize() {
        const isMinimized = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.IS_MINIMIZED);
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.IS_MINIMIZED, !isMinimized);
        console.log(`${index_1.NAME.PREFIX}toggleMinimize: ${isMinimized} -> ${!isMinimized}.`);
        this.onMinimized && this.onMinimized(isMinimized, !isMinimized);
    }
    _executeExternalBeforeCalling() {
        this.beforeCalling && this.beforeCalling();
    }
    _executeExternalAfterCalling() {
        this.afterCalling && this.afterCalling();
    }
    // ========================【TUICallKit 组件属性设置方法】========================
    setVideoDisplayMode(displayMode) {
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.DISPLAY_MODE, displayMode);
    }
    setVideoResolution(resolution) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                if (!resolution)
                    return;
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.VIDEO_RESOLUTION, resolution);
                yield this._tuiCallEngine.setVideoQuality(resolution);
            }
            catch (error) {
                console.warn(`${index_1.NAME.PREFIX}setVideoResolution failed, error: ${error}.`);
            }
        });
    }
    // =========================【 miniProgram 私有公共方法】=========================
    // 处理用户异常退出的情况，处理了右滑退出，以及返回退出的情况。
    _handleExceptionExit() {
        return __awaiter(this, void 0, void 0, function* () {
            const callStatus = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_STATUS);
            const callRole = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_ROLE);
            // 在呼叫状态下, 被叫调用 reject，主叫调用 hangup
            if (callStatus === index_1.CallStatus.CALLING) {
                callRole === index_1.CallRole.CALLER && (yield this.hangup());
                callRole === index_1.CallRole.CALLEE && (yield this.reject());
            }
            // 在通话状态下, 统一调用 hangup 接口
            callStatus === index_1.CallStatus.CONNECTED && (yield this.hangup());
        });
    }
    _setLocalUserInfoAudioVideoAvailable(isAvailable, type) {
        let localUserInfo = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO);
        if (type === index_1.NAME.AUDIO) {
            localUserInfo = Object.assign(Object.assign({}, localUserInfo), { isAudioAvailable: isAvailable });
        }
        if (type === index_1.NAME.VIDEO) {
            localUserInfo = Object.assign(Object.assign({}, localUserInfo), { isVideoAvailable: isAvailable });
        }
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO, localUserInfo);
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN, localUserInfo);
    }
    _updateCallStoreBeforeCall(type, remoteUserInfoList, groupID) {
        return __awaiter(this, void 0, void 0, function* () {
            const callTips = groupID || TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.IS_MINIMIZED) ? index_2.CallTips.CALLER_GROUP_CALLING_MSG : index_2.CallTips.CALLER_CALLING_MSG;
            let updateStoreParams = {
                [index_1.NAME.CALL_MEDIA_TYPE]: type,
                [index_1.NAME.CALL_ROLE]: index_1.CallRole.CALLER,
                [index_1.NAME.REMOTE_USER_INFO_LIST]: remoteUserInfoList,
                [index_1.NAME.REMOTE_USER_INFO_EXCLUDE_VOLUMN_LIST]: remoteUserInfoList,
                [index_1.NAME.IS_GROUP]: !!groupID,
                [index_1.NAME.CALL_TIPS]: (0, index_2.t)(callTips),
                [index_1.NAME.GROUP_ID]: groupID
            };
            const pusher = { enableCamera: type === index_1.CallMediaType.VIDEO, enableMic: true }; // mini 默认打开麦克风
            updateStoreParams = Object.assign(Object.assign({}, updateStoreParams), { [index_1.NAME.PUSHER]: pusher });
            TUIStore.updateStore(updateStoreParams, index_1.StoreName.CALL);
            const callStatus = yield (0, miniProgram_1.beforeCall)(type, this); // 如果没有权限, 此时为 false. 因此需要在 call 后设置为 calling. 和 web 存在差异
            console.log(`${index_1.NAME.PREFIX}mini beforeCall return callStatus: ${callStatus}.`);
            TUIStore.update(index_1.StoreName.CALL, index_1.NAME.CALL_STATUS, callStatus);
            const remoteUserInfoLists = yield (0, utils_1.getRemoteUserProfile)(remoteUserInfoList.map(obj => obj.userId), this.getTim(), TUIStore);
            if (remoteUserInfoLists.length > 0) {
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST, remoteUserInfoLists);
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_EXCLUDE_VOLUMN_LIST, remoteUserInfoLists);
            }
        });
    }
    _updateCallStoreAfterCall(userIdList, response) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            if (response) {
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.IS_CLICKABLE, true);
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.ROOM_ID, response.roomID);
                this._callTUIService({ message: (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.message });
                response.pusher && TUIStore.update(index_1.StoreName.CALL, index_1.NAME.PUSHER, response.pusher);
                const callMediaType = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_MEDIA_TYPE);
                (callMediaType === index_1.CallMediaType.VIDEO) && (yield this.openCamera(index_1.NAME.LOCAL_VIDEO));
                this.setSoundMode(callMediaType === index_1.CallMediaType.AUDIO ? index_1.AudioPlayBackDevice.EAR : index_1.AudioPlayBackDevice.SPEAKER);
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.CALL_STATUS, index_1.CallStatus.CALLING); // 小程序未授权时, 此时状态为 idle; web 直接设置为 calling
                const localUserInfo = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO);
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO, Object.assign(Object.assign({}, localUserInfo), { isEnter: true }));
                TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN, Object.assign(Object.assign({}, localUserInfo), { isEnter: true }));
                this._setLocalUserInfoAudioVideoAvailable(true, index_1.NAME.AUDIO); // web && mini, default open audio
            }
            else {
                this._resetCallStore();
            }
        });
    }
    _resetCurrentDevice() {
        // 挂断后，重置当前摄像头，麦克风和扬声器为默认设备
        const { cameraList, microphoneList, speakerList } = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.DEVICE_LIST);
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.DEVICE_LIST, { microphoneList, cameraList, speakerList,
            currentCamera: (cameraList === null || cameraList === void 0 ? void 0 : cameraList[0]) || {},
            currentMicrophone: (microphoneList === null || microphoneList === void 0 ? void 0 : microphoneList[0]) || {},
            currentSpeaker: (speakerList === null || speakerList === void 0 ? void 0 : speakerList[0]) || {}
        });
    }
    _resetCallStore() {
        const oldStatusStr = (0, utils_1.generateStatusChangeText)(TUIStore);
        this._stopTimer();
        // localUserInfo, language 在通话结束后不需要清除
        // callStatus 清除需要通知; isMinimized 也需要通知（basic-vue3 中切小窗关闭后, 再呼叫还是小窗, 因此需要通知到组件侧）
        // isGroup 也不清除(engine 先抛 cancel 事件, 再抛 reject 事件)
        // displayMode、videoResolution 也不能清除, 组件不卸载, 这些属性也需保留, 否则采用默认值.
        // enableFloatWindow 不清除：开启/关闭悬浮窗功能。
        let notResetOrNotifyKeys = Object.keys(index_1.CALL_DATA_KEY).filter((key) => {
            switch (index_1.CALL_DATA_KEY[key]) {
                case index_1.NAME.CALL_STATUS:
                case index_1.NAME.LANGUAGE:
                case index_1.NAME.IS_GROUP:
                case index_1.NAME.DISPLAY_MODE:
                case index_1.NAME.VIDEO_RESOLUTION:
                case index_1.NAME.ENABLE_FLOAT_WINDOW:
                case index_1.NAME.LOCAL_USER_INFO:
                case index_1.NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN: {
                    return false;
                }
                default: {
                    return true;
                }
            }
        });
        notResetOrNotifyKeys = notResetOrNotifyKeys.map(key => index_1.CALL_DATA_KEY[key]);
        TUIStore.reset(index_1.StoreName.CALL, notResetOrNotifyKeys);
        const callStatus = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.CALL_STATUS);
        callStatus !== index_1.CallStatus.IDLE && TUIStore.reset(index_1.StoreName.CALL, [index_1.NAME.CALL_STATUS], true); // callStatus reset need notify
        TUIStore.reset(index_1.StoreName.CALL, [index_1.NAME.IS_MINIMIZED], true); // isMinimized reset need notify
        TUIStore.reset(index_1.StoreName.CALL, [index_1.NAME.IS_EAR_PHONE], true); // isEarPhone reset need notify
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO, Object.assign(Object.assign({}, TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO)), { isVideoAvailable: false, isAudioAvailable: false }));
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN, Object.assign(Object.assign({}, TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN)), { isVideoAvailable: false, isAudioAvailable: false }));
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST, []);
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_EXCLUDE_VOLUMN_LIST, []);
        this._resetCurrentDevice();
        const newStatusStr = (0, utils_1.generateStatusChangeText)(TUIStore);
        if (oldStatusStr !== newStatusStr) {
            this.statusChanged && this.statusChanged({ oldStatus: oldStatusStr, newStatus: newStatusStr });
        }
    }
    _noDevicePermissionToast(error, type) {
        if ((0, common_utils_1.handleNoDevicePermissionError)(error)) {
            let text = '';
            if (type === index_1.CallMediaType.AUDIO) {
                text = (0, utils_1.generateText)(TUIStore, index_2.CallTips.NO_MICROPHONE_DEVICE_PERMISSION);
            }
            if (type === index_1.CallMediaType.VIDEO) {
                text = (0, utils_1.generateText)(TUIStore, index_2.CallTips.NO_CAMERA_DEVICE_PERMISSION);
            }
            text && TUIStore.update(index_1.StoreName.CALL, index_1.NAME.TOAST_INFO, { text, type: index_1.NAME.ERROR });
            console.error(`${index_1.NAME.PREFIX}call failed, error: ${error.message}.`);
        }
    }
    // 通话时长更新
    _startTimer() {
        if (this._timerId === -1) {
            this._startTimeStamp = (0, common_utils_1.performanceNow)();
            this._timerId = timer_1.default.run(index_1.NAME.TIMEOUT, this._updateCallDuration.bind(this), { delay: 1000 });
        }
    }
    _updateCallDuration() {
        const callDurationNum = Math.round(((0, common_utils_1.performanceNow)() - this._startTimeStamp) / 1000); // miniProgram stop timer when background
        const callDurationStr = (0, common_utils_1.formatTime)(callDurationNum);
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.CALL_DURATION, callDurationStr);
    }
    _stopTimer() {
        if (this._timerId !== -1) {
            timer_1.default.clearTask(this._timerId);
            this._timerId = -1;
        }
    }
    _deleteRemoteUser(userIdList) {
        if (userIdList.length === 0)
            return;
        let remoteUserInfoList = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST);
        userIdList.forEach((userId) => {
            remoteUserInfoList = remoteUserInfoList.filter((obj) => obj.userId !== userId);
        });
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_LIST, remoteUserInfoList);
        TUIStore.update(index_1.StoreName.CALL, index_1.NAME.REMOTE_USER_INFO_EXCLUDE_VOLUMN_LIST, remoteUserInfoList);
    }
    _analyzeEventData(event) {
        return (event === null || event === void 0 ? void 0 : event.data) || {}; // mini INVITED
    }
    // =========================【调用 chat api】=========================
    // 获取群成员
    getGroupMemberList(count, offset) {
        return __awaiter(this, void 0, void 0, function* () {
            const groupID = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.GROUP_ID);
            let groupMemberList = yield (0, utils_1.getGroupMemberList)(groupID, this.getTim(), count, offset);
            return groupMemberList;
        });
    }
    // 获取群信息
    getGroupProfile() {
        return __awaiter(this, void 0, void 0, function* () {
            const groupID = TUIStore.getData(index_1.StoreName.CALL, index_1.NAME.GROUP_ID);
            return yield (0, utils_1.getGroupProfile)(groupID, this.getTim());
        });
    }
    _watchTUIStore() {
        TUIStore === null || TUIStore === void 0 ? void 0 : TUIStore.watch(index_1.StoreName.CALL, {
            [index_1.NAME.CALL_STATUS]: this._handleCallStatusChange,
        });
    }
    _unwatchTUIStore() {
        TUIStore === null || TUIStore === void 0 ? void 0 : TUIStore.unwatch(index_1.StoreName.CALL, {
            [index_1.NAME.CALL_STATUS]: this._handleCallStatusChange,
        });
    }
    // =========================【web 融合 chat 提供的方法】=========================
    bindTUICore(TUICore) {
        this._TUICore = TUICore;
    }
    // 下面方法用于接入 TUICore
    _callTUIService(params) {
        const { message } = params || {};
        tui_core_1.TUICore.callService({
            serviceName: tui_core_1.TUIConstants.TUIChat.SERVICE.NAME,
            method: tui_core_1.TUIConstants.TUIChat.SERVICE.METHOD.UPDATE_MESSAGE_LIST,
            params: { message },
        });
    }
    onNotifyEvent(eventName, subKey) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                if (eventName === tui_core_1.TUIConstants.TUILogin.EVENT.LOGIN_STATE_CHANGED) {
                    if (subKey === tui_core_1.TUIConstants.TUILogin.EVENT_SUB_KEY.USER_LOGIN_SUCCESS) {
                        // TUICallkit 收到登录成功时执行自己的业务逻辑处理
                        // @ts-ignore
                        const { chat, userID, userSig, SDKAppID } = tui_core_1.TUILogin.getContext();
                        yield this.init({ tim: chat, userID, userSig, sdkAppID: SDKAppID, isFromChat: true });
                    }
                    else if (subKey === tui_core_1.TUIConstants.TUILogin.EVENT_SUB_KEY.USER_LOGOUT_SUCCESS) {
                        yield this.destroyed();
                    }
                }
            }
            catch (error) {
                console.error(`${index_1.NAME.PREFIX}TUICore onNotifyEvent failed, error: ${error}.`);
            }
        });
    }
    onCall(method, params) {
        return __awaiter(this, void 0, void 0, function* () {
            if (method === tui_core_1.TUIConstants.TUICalling.SERVICE.METHOD.START_CALL) {
                yield this._handleTUICoreOnClick(params, params.type);
            }
        });
    }
    _handleTUICoreOnClick(options, type) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const { groupID, userIDList = [] } = options, rest = __rest(options, ["groupID", "userIDList"]);
                if (groupID) {
                    yield this.groupCall(Object.assign({ groupID, userIDList, type }, rest));
                }
                else if (userIDList.length === 1) {
                    yield this.call(Object.assign({ userID: userIDList[0], type }, rest));
                }
            }
            catch (error) {
                console.debug(error);
            }
        });
    }
    onGetExtension(extensionID, params) {
        if (extensionID === tui_core_1.TUIConstants.TUIChat.EXTENSION.INPUT_MORE.EXT_ID) {
            const list = [];
            const audioCallExtension = {
                weight: 1000,
                text: '语音通话',
                icon: index_1.AudioCallIcon,
                data: {
                    name: 'voiceCall',
                },
                listener: {
                    onClicked: (options) => __awaiter(this, void 0, void 0, function* () { return yield this._handleTUICoreOnClick(options, options.type || index_1.CallMediaType.AUDIO); }), // 点击时发起通话
                },
            };
            const videoCallExtension = {
                weight: 900,
                text: '视频通话',
                icon: index_1.VideoCallIcon,
                data: {
                    name: 'videoCall',
                },
                listener: {
                    onClicked: (options) => __awaiter(this, void 0, void 0, function* () { return yield this._handleTUICoreOnClick(options, options.type || index_1.CallMediaType.VIDEO); }), // 点击时发起通话
                },
            };
            if (!(params === null || params === void 0 ? void 0 : params.filterVoice)) {
                list.push(audioCallExtension);
            }
            if (!(params === null || params === void 0 ? void 0 : params.filterVideo)) {
                list.push(videoCallExtension);
            }
            return list;
        }
    }
}
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    (0, index_3.paramValidate)(index_3.VALIDATE_PARAMS.init),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "init", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    (0, index_3.paramValidate)(index_3.VALIDATE_PARAMS.call),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "call", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    (0, index_3.paramValidate)(index_3.VALIDATE_PARAMS.groupCall),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "groupCall", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    (0, index_3.paramValidate)(index_3.VALIDATE_PARAMS.inviteUser),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "inviteUser", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    (0, index_3.paramValidate)(index_3.VALIDATE_PARAMS.joinInGroupCall),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "joinInGroupCall", null);
__decorate([
    (0, index_3.paramValidate)(index_3.VALIDATE_PARAMS.setLanguage),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", void 0)
], TUICallService.prototype, "setLanguage", null);
__decorate([
    (0, index_3.paramValidate)(index_3.VALIDATE_PARAMS.enableFloatWindow),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Boolean]),
    __metadata("design:returntype", void 0)
], TUICallService.prototype, "enableFloatWindow", null);
__decorate([
    (0, index_3.paramValidate)(index_3.VALIDATE_PARAMS.setSelfInfo),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "setSelfInfo", null);
__decorate([
    (0, index_3.paramValidate)(index_3.VALIDATE_PARAMS.setCallingBell),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "setCallingBell", null);
__decorate([
    (0, index_3.paramValidate)(index_3.VALIDATE_PARAMS.enableMuteMode),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Boolean]),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "enableMuteMode", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "accept", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "hangup", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "reject", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "openCamera", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "closeCamera", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "openMicrophone", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "closeMicrophone", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", void 0)
], TUICallService.prototype, "switchScreen", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "switchCallMediaType", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "switchCamera", null);
__decorate([
    (0, index_3.avoidRepeatedCall)(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", void 0)
], TUICallService.prototype, "setSoundMode", null);
__decorate([
    (0, index_3.paramValidate)(index_3.VALIDATE_PARAMS.setVideoDisplayMode),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", void 0)
], TUICallService.prototype, "setVideoDisplayMode", null);
__decorate([
    (0, index_3.paramValidate)(index_3.VALIDATE_PARAMS.setVideoResolution),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], TUICallService.prototype, "setVideoResolution", null);
exports.default = TUICallService;
