/*eslint-disable*/

import Emiter from 'Emiter';
import MessageTypes from 'MessageTypes';
import Loger from 'Loger';
import everSocket from 'everSocket';
import pdu from 'pdus/index';
import PduType from 'pdus/PduType';
import PduConsts from 'pdus/PduConsts';
import ApeConsts from 'apes/ApeConsts';
import ConferApe from 'apes/ConferApe';
import ArrayBufferUtil from 'libs/ArrayBufferUtil';
import Base64 from 'base64-js';
import GlobalConfig from 'GlobalConfig';
import EngineUtils from 'EngineUtils';

let loger = Loger.getLoger('MCU');

class MCU extends Emiter {
    constructor() {
        super();
        this._apes = {};
        this._everSocket = everSocket;
        this._everSocket.on(everSocket.OPEN, this._everSocketOpenHandler.bind(this));
        this._everSocket.on(everSocket.MESSAGE, this._everSocketMsgReceivedHandler.bind(this));
        this._everSocket.on(everSocket.CLOSED, this._everSocketCloseHandler.bind(this));
        this._everSocket.on(everSocket.ERROR, this._everSocketErrorHandler.bind(this));
    }

    // 注册Ape
    registerApe(ape) {
        this._apes[ape._session_id] = ape;
    }

    // EverSocket建立通道完毕
    _everSocketOpenHandler() {
        this._sendJoinClassRequest();
    }

    // EverSocket连接断开
    _everSocketCloseHandler() {
        //如果已经是断开状态,不需要多次发送异常消息
        if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_3.code) {
            loger.warn('已经断开连接->');
            return;
        }
        GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_3);
        this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_SOCKET_DISCONNECT);
    }

    //EverSocket错误异常
    _everSocketErrorHandler(_errorCode) {
        //this._emit(MessageTypes.MCU_ERROR, _errorCode);
        //如果自动重连次数已经达到最大值,重新选点
        if (_errorCode == everSocket.ERR_SOCKET_RECONNECT_FAILED) {
            this._emit(MessageTypes.SWITCH_MCU_IP);
        }
    }

    //MCU-发送加入课堂请求
    _sendJoinClassRequest() {
        //const classInfo = this.classInfo;
        loger.log('MCU-发送加入课堂请求.');
        loger.log(this.classInfo);
        var descriptorPdu = new pdu['RCConferenceDescriptorPdu'];
        descriptorPdu.id = this.classInfo.classId;
        descriptorPdu.name = this.classInfo.className || "";
        descriptorPdu.mode = 0;
        descriptorPdu.capacity = 1;

        var joinRequestPdu = new pdu['RCConferenceJoinRequestPdu'];
        joinRequestPdu.type = 2;
        joinRequestPdu.initiator = this.classInfo.nodeId;
        joinRequestPdu.nodeType = PduConsts.NT_TERMINAL; //normal
        joinRequestPdu.classDescription = descriptorPdu;//  classDescription

        let pduMsg = pdu.create_join_class_request_pdu(
            joinRequestPdu.type,
            this.classInfo.nodeId,
            this.classInfo.classId,
            0,
            ApeConsts.BROADCAST_CHANNEL_ID,
            true,
            PduConsts.DP_TOP,
            this.classInfo.topNodeID,
            PduConsts.SEG_ONCE
        );

        pduMsg.set("site", this.classInfo.siteId);//课堂号对应的名称
        pduMsg.set("userId", this.classInfo.userId);
        pduMsg.set("userName", Base64.fromByteArray(ArrayBufferUtil.strToUint8Array(this.classInfo.userName)));
        pduMsg.set("userRole", this.classInfo.userRole);
        pduMsg.set("deviceType", "" + GlobalConfig.deviceType);
        pduMsg.set("data", joinRequestPdu.toArrayBuffer());

        this._everSocket.send(pduMsg.toArrayBuffer());
    }

    // EverSocket底层消息处理
    _everSocketMsgReceivedHandler(data) {
        let pduMsg = pdu.decode_pdu(data);
        let pduType = pduMsg.get("type");
        let pduData = pduMsg.get("data");
        //loger.data('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId);
        //loger.log('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId);
        switch (pduType) {
            case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE:
                //加入课堂请求返回数据处理
                let joinConfPdu = pdu['RCConferenceJoinResponsePdu'].decode(pduData);
                let pduResultCode = joinConfPdu.result;
                loger.warn('RCPDU_CONNECT_PROVIDER_RESPONSE  ->pduResultCode:' + pduResultCode);
                switch (pduResultCode) {
                    case PduConsts.RET_SUCCESS:
                        //加入成功
                        this._updateMCUConfInfoDescription(joinConfPdu.classDescription);
                        this._emit(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this.classInfo);
                        break;
                    case PduConsts.RET_FULL_CAPACITY:
                        this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FULL);
                        //this._emit(MessageTypes.CLASS_JOIN_FAILED,MessageTypes.ERR_CLASS_JOIN_FULL);
                        //this._emit(MessageTypes.CLASS_JOIN_FULL);
                        break;
                    default:
                        loger.arn('JoinConfPdu-未知类型-等待处理.', pduResultCode);
                        break
                }
                break;
            case PduType.RCPDU_SEND_DATA_REQUEST:
                //先判断当前消息属于哪个APE 根据 sessionId来判断
                let ape = this._apes[pduMsg.sessionId];
                let sessionLabel = ApeConsts(pduMsg.sessionId);
                if (ape) {
                    let subTypeLabel = pdu.id2type(pduMsg.subType);
                    //loger.log('MCU-SecondLayer封装消息', 'sessionId', sessionLabel, pduMsg.sessionId, 'subtype', subTypeLabel, pduMsg.subType);

                    loger.warn('接收服务端消息----------------->subType->', pduMsg.subType, GlobalConfig.mcuDelay, GlobalConfig.messageDelay);
                    //延迟处理消息(3个条件--->ape允许延迟&&客户端设置需要延迟&&Sass设置的延迟时间大于0)
                    if (ape._apeDelayed && GlobalConfig.messageDelay && GlobalConfig.mcuDelay > 0) {
                        loger.warn('延迟处理消息->', GlobalConfig.mcuDelay);
                        setTimeout(() => {
                            //this._pduRegAdapterHandler(regBuffer, seekTime);
                            ape._emit(pduMsg.subType, pduMsg.data);
                        }, GlobalConfig.mcuDelay * 1000);//mcuDelay单位是秒,
                        // 这里需要换算为毫秒
                        return;
                    }
                    ape._emit(pduMsg.subType, pduMsg.data);
                } else {
                    loger.warn(sessionLabel + '尚未注册');
                }
                break;
            default:
                loger.warn('PDU-未知类型-等待处理.', pduType);
        }
    }

    _updateMCUConfInfoDescription(_data) {
        // let _mcuConfDesc=new pdu['RCConferenceDescriptorPdu'].decode(mcuConfDesc);
        loger.log('_updateMCUConfInfoDescription.');
        //let classDescription=new pdu['RCConferenceDescriptorPdu'].decode(_data);
        loger.log(_data);
        //let info = this.mcuClassInfo.info;
        //info._conference_name = ArrayBufferUtil.uint8ArrayToStr(mcuConfDesc.name, 0);
        //info._capacity = mcuConfDesc.capacity;
        //info._mode = mcuConfDesc.mode;
    }

    // MU服务是否连接
    get connected() {
        if (this._everSocket && this._everSocket.connected)
            return true;
        return false;
    }

    // 课堂发送消息 -- 消息同意序列号
    send(msg) {
        if (this.connected) {
            loger.log('发送数据到服务端-------------------->');
            this._everSocket.send(msg.toArrayBuffer());
        } else {
            loger.log('发送数据到服务端-------------------->失败->未连接到服务端');
            this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_SOCKET_DISCONNECT);
        }
    }

    // 主动断开MCU连接
    leaveMCU() {
        for (let ape in this._apes) {
            this._apes[ape].stopApe();
        }
        loger.log('leaveMCU');
        GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_3);
        GlobalConfig.classJoinSuccess=false;
        this._everSocket.end();
    }

    // 主动建立MCU连接
    joinMCU(_classInfo) {
        loger.log('开始建立EverSocket通道.');
        GlobalConfig.classJoinSuccess=false;
        loger.log(_classInfo);
        _classInfo.classId = parseInt(_classInfo.classId); // classId 必须整形
        this.classInfo = _classInfo;
        // 创建刷新nodeId
        this.classInfo.nodeId = EngineUtils.creatSoleNumberFromTimestamp();
        GlobalConfig.nodeId = this.classInfo.nodeId;//这是标识自己身份的id

        let nodeInfoRecordPdu = new pdu['RCNodeInfoRecordPdu'];
        nodeInfoRecordPdu.name = this.classInfo.userName;
        nodeInfoRecordPdu.nodeId = this.classInfo.nodeId;
        nodeInfoRecordPdu.userId = this.classInfo.userId;
        nodeInfoRecordPdu.role = ApeConsts.userTypesToId[this.classInfo.userRole] || 1; //NR_NORMAL用户的身份,根据用户登录时的身份设置
        nodeInfoRecordPdu.level = 0;
        nodeInfoRecordPdu.handUpTime=0;
        nodeInfoRecordPdu.openCamera=0;
        nodeInfoRecordPdu.openMicrophones=0;
        nodeInfoRecordPdu.microphones=GlobalConfig.microphones;
        nodeInfoRecordPdu.cameras=GlobalConfig.cameras;
        nodeInfoRecordPdu.videoQuality=GlobalConfig.videoQuality;//设置分辨率的
        nodeInfoRecordPdu.userIp=GlobalConfig.userIp;

        let conferenceRecord = {}; //RCConferenceRecord_T
        conferenceRecord._conference_id = this.classInfo.classId;
        conferenceRecord._top_node_id = this.classInfo.topNodeID;

        this.mcuClassInfo = {}; //RCMeetingInfo_T
        this.mcuClassInfo.self = nodeInfoRecordPdu;
        this.mcuClassInfo.info = conferenceRecord;

        // 内部mcuConfInfo
        this.classInfo.mcuClassInfo = this.mcuClassInfo;

        //开启EverSocket
        this._everSocket.begin(this.classInfo.MCUServerIP, this.classInfo.MCUServerPort);
    }

    //切换MCU的ip
    switchMCUIp(_classInfo) {
        if (_classInfo && _classInfo.MCUServerIP) {
            this.classInfo.MCUServerIP = _classInfo.MCUServerIP;
            this.classInfo.MCUServerPort = _classInfo.MCUServerPort;
            if (this._everSocket) {
                this._everSocket.switchSocketIp(this.classInfo.MCUServerIP, this.classInfo.MCUServerPort);
            }
        }
    }
}

export default new MCU;