/*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);
    }
    switch(_errorCode){
      case everSocket.ERR_SOCKET_MAX_RECONNECT_FAILED:
        //mcu已经达到最大重连次数,不再重连
        this._emit(MessageTypes.SOCKET_MAX_RECONNECT_FAILED);
        break;
      case everSocket.ERR_SOCKET_RECONNECT_FAILED:
        //重连失败,尝试更换MCU再重连
        this._emit(MessageTypes.SWITCH_MCU_IP);
        break;
      default :
        break;
    }
  }

  //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(),joinRequestPdu.type);
  }

  // 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,
          GlobalConfig.mcuDelay,
          GlobalConfig.messageDelay);*/

        //延迟处理消息(3个条件--->ape允许延迟&&客户端设置需要延迟&&Sass设置的延迟时间大于0)
        if (GlobalConfig.messageDelay &&
          GlobalConfig.messageDelay.indexOf(sessionLabel) !== -1 &&
          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(),msg.type);
    } else {
      loger.warn('发送数据到服务端-------------------->失败->未连接到服务端');
      this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_SOCKET_DISCONNECT);
    }
  }

  // 主动断开MCU连接
  leaveMCU() {
    loger.log('断开MCU连接');
    GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_3);
    GlobalConfig.classJoinSuccess = false;
    if( this._everSocket){
      this._everSocket.end();
    }
  }

  // 主动建立MCU连接
  joinMCU(_classInfo) {
    if(GlobalConfig.classExit==true){
      loger.warn("已经关闭课堂->不再连接MCU");
      return;
    }
    loger.log('开始建立EverSocket通道.');
    GlobalConfig.classJoinSuccess = false;
    loger.log(_classInfo);
    _classInfo.classId = parseInt(_classInfo.classId); // classId 必须整形
    this.classInfo = _classInfo;

    // 创建刷新nodeId
    //let randNodeId =parseInt(Math.random()*1000)+""+parseInt(Math.random()*1000)+""+parseInt(Math.random()*1000);
    let randNodeId=""+ EngineUtils.getRandomInt(1000,3)+ EngineUtils.getRandomInt(1000,3)+ EngineUtils.getRandomInt(1000,3);
    //生成的字符串nodeId转换为数字
    randNodeId=parseInt(randNodeId);

    this.classInfo.nodeId =randNodeId; //EngineUtils.creatSoleNumberFromTimestamp();
    GlobalConfig.joinTimestamp=EngineUtils.creatSoleNumberFromTimestamp();
    GlobalConfig.nodeId = this.classInfo.nodeId; //这是标识自己身份的id
    console.log("创建nodeId",GlobalConfig.nodeId);

    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.joinTimestamp= GlobalConfig.joinTimestamp||EngineUtils.creatSoleNumberFromTimestamp();
    nodeInfoRecordPdu.level = 0;
    nodeInfoRecordPdu.handUpTime = 0;
    nodeInfoRecordPdu.selfDisEnableDrawTime = 1;
    nodeInfoRecordPdu.openCamera = 0;
    nodeInfoRecordPdu.openMicrophones = 0;
    nodeInfoRecordPdu.microphones = GlobalConfig.microphones;
    nodeInfoRecordPdu.cameras = GlobalConfig.cameras;
    nodeInfoRecordPdu.videoQuality = GlobalConfig.videoQuality; //设置分辨率的
    nodeInfoRecordPdu.userIp = GlobalConfig.userIp;

    nodeInfoRecordPdu.deviceType = GlobalConfig.deviceType;
    nodeInfoRecordPdu.language = GlobalConfig.language;
    nodeInfoRecordPdu.explorer = GlobalConfig.explorer;
    nodeInfoRecordPdu.explorerVersion = GlobalConfig.explorerVersion;
    nodeInfoRecordPdu.os = GlobalConfig.os;

    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;