interface IParams {
  // 签名供验证
  sign: string;
  // 业务标识
  biz_name: string;
  // 业务标识，mPaaS 下对应的 appId，可以从 mPaaS 控制台 中获取。
  sub_biz: string | null;
  // 用户唯一标识，由客户端透传而来。
  uid: string;
  /**
   * 房间服务器地址，公有云中金区环境与非金区环境的房间服务器地址不同，您可以按您当前的环境选择房间服务器的地址。
   * 非金区：wss://mrtc.mpaas.cn-hangzhou.aliyuncs.com/ws
   * 金区：wss://room.mrtc-fin.cn-shanghai.aliyuncs.com/ws
   */
  room_server_url: string
}

interface IConfig {

}

interface IParticipants {

}

/**
 * @name CommandInfo
 * @description 指令类型
 * @enum 'subtitle' | 'feedText'
 * @zhEnum '字幕' | '反馈文本-开始播报'
 */
type CommandInfo = 'subtitle' | 'feedText';

interface ReceiveData {
  // 语音播报内容
  timelines: any[];
  // 语音播报内容文本
  oriText: string;
  // 指令，通过这个类型来判断是开始播报内容，还增加排队打印的数据
  command: CommandInfo;
  // 播放所需时长
  duration: number;
  // 当前为本次回答的第几条0为第一条数据
  textIndex: number;
  // 这个暂时无用
  order: number;
  sessionId: number;
  queryId: string;
  // 最后一条
  finalRequest: boolean;
  // 回到文字的类型（通知，欢迎，回复）
  sourceType: 'notify' | 'welcome' | 'reply';
  // 语言类型是否为英文
  wholeEnglish: boolean;
  // 执行类型
  executeType: 'callbackAction';
  // 参数
  paramMap: {
    type: 'BEGIN_PLAY' | 'END' | 'START';
  };
  // 音视频数据,string类型,里面是json字符串ReceiveData
  data: string;
  // 排序
  sortId: number;
  // 语音识别结束
  asrEnd: {
    text: string;
    traceId: string;
  };
  // 语音识别，流式输出
  asrChange: {
    text: string;
    traceId: string;
  };
  // 图片上传信息下发
  fileUpload: {
    fileName: string;
    fileUrl: string;
    fileType: 'IMAGE';
    fileSource: 'USER_UPLOAD' | 'SYSTEM_CONVERT';
    operateTime: number;
  };
  // 图片解析
  imageParseStatus: {
    status: 'ok' | 'fail';
    fileName: string;
  };
}
export class MRTCService {
  controller: null; // 实例化SDK
  publishSid: string | null; // 流文件
  feedId: string | null; // 流文件
  token: string | null; // token
  roomId: string | null; // 房间ID
  bizName: string | null; // bizName
  userId: string | null; // userId
  room_server_url: string | null; // room_server_url
  subBiz: string | null;  // 业务标识，mPaaS 下对应的 appId，可以从 mPaaS 控制台 中获取。 2021005106669123
  sign: string | null; // sign
  queryId: string | null; // 请求id，端上产生，每次不一样，推荐使用uuid
  sessionId: string | null; // 唯一会话id，整通会话中需要保持一致
  participants: any;// 房间列表

  callback: any; // 语音回答

  constructor(params, callback) {
    this.callback = callback
    let {
      bizName,
      sign,
      subBiz,
      userId,
      token,
      roomId,
      sessionId,
      queryId
    } = params
    this.sessionId = sessionId
    this.queryId = queryId
    this.roomId = roomId
    // this.bizName = 'AB3FD4290636A369A52C71F3C2C292E0'
    // this.subBiz = 'ONEXPRE8B4D3E9271559'
    this.bizName = '07E1DDB4D4F286887D521D0DBBCFE7A6'
    this.subBiz = 'ALIPUB4F56FA6211535';
    this.userId = userId
    this.token = token
    // this.room_server_url = 'wss://premrtc-yunyou.mpaas.cn-hangzhou.aliyuncs.com/ws'
    this.room_server_url = 'wss://mrtc.mpaas.cn-hangzhou.aliyuncs.com/ws'
    this.sign = sign
    this.controller = new MeetingController();  // 实例化 SDK
    console.log(this)
    console.log(this.controller, {
      sign: this.sign,
      biz_name: this.bizName,
      sub_biz: this.subBiz,
      uid: this.userId,
      room_server_url: this.room_server_url
    })
    // this.onConnect()
  }

  /**
   * 所有成功的监听回调
   */
  onListeningSuccessMethod() {
    let _this = this
    _this.OnReceiveTextMsg()

    /**
     * 订阅媒体流成功
     * @param sid 流 ID
     * @param feedId 流信息
     * @constructor
     */
    _this.controller.OnSubscribeSucc = (sid: string, feedId: string) => {
      console.log('【Lynn】订阅媒体流成功', sid, feedId, _this.feedId)
      // sid等于获取的流信息，不再次订阅
      if (sid === _this.feedId) {
        return;
      }
      _this.controller.Subscribe({
        subscribe_video_id: 'digital_human_video-player', // 用于展示订阅的视频流 视频控件ID
        subscribe_audio_id: 'digital_human_audio-player', // 用于展示订阅的音频流 音频控件ID
        subscribe_streamId_id: 'feedId',// 用于展示订阅的流
        feedId_id: 'feedId',// 用于展示 feedId
        need_volume_analyser: true, // 默认为 false，是否需要实时音量值。
        feedId: sid,// feedId
      })
    }

    /**
     * 加入房间成功
     * @constructor
     */
    _this.controller.OnJoinRoomSucc = () => {
      console.log('【Lynn】加入房间成功')
    }

    /**
     * 发布媒体流成功
     * @param streamId 发布媒体流的 ID
     * @constructor
     */
    _this.controller.OnPublishSucc = (streamId: string) => {
      console.log('【Lynn===】发布媒体流成功 OnPublishSucc', streamId)
      // 存储流信息
      _this.publishSid = streamId
      // 自定义逻辑
      _this.onTurnOnTheMicrophone(false)
    }

    /**
     * 初始化房间成功
     * @constructor
     */
    _this.controller.OnInitRoomConfigOK = async () => {
      console.log('【Lynn】初始化房间成功')
      _this.OnRoomAttendanceList({
        subscribe_video_id: 'digital_human_video-player', // 用于展示订阅的视频流 视频控件ID
        subscribe_audio_id: 'digital_human_audio-player', // 用于展示订阅的音频流 音频控件ID
        subscribe_streamId_id: 'streamId',// 用于展示订阅的流
        feedId_id: 'feedId',// 用于展示 feedId
        need_volume_analyser: true, // 默认为 false，是否需要实时音量值。
      })
      /**
       * 加入房间
       * @param roomId 房间ID
       * @param token token
       * @param sign sign签名
       */
      _this.controller.JoinRoom(_this.roomId, _this.token, _this.sign)
    }

    /**
     * 发送文本消息成功
     * @param msgId 消息 ID
     * @constructor
     */
    _this.controller.OnSendTextMsgSucc = (msgId: string) => {
      console.log('【Lynn】发送文本消息成功', msgId)
    }

    _this.controller.OnConnectOK = () => {
      let config: IConfig = {
        auto_publish_subscribe: 2, // 2：自动发布。
        media_type: 2,
        publish_device: 1,
        initSubscribe:  {
          subscribe_video_id: 'digital_human_video-player', // 用于展示订阅的视频流 视频控件ID
          subscribe_audio_id: 'digital_human_audio-player', // 用于展示订阅的音频流 音频控件ID
          subscribe_streamId_id: 'streamId',// 用于展示订阅的流
          feedId_id: 'feedId',// 用于展示 feedId
          // need_volume_analyser: true, // 默认为 false，是否需要实时音量值。
        },
        initPublish: [
          {
            publish_streamId_id: "publish_streamId1",
            publish_tag: "VIDEO_SOURCE_CAMERA",
            publish_video_id: "publish_video1",
          }
        ]
      }
      console.log('【Lynn】监听连接成功', config)
      _this.controller.InitRoomConfig(config)
    }


    // 断开连接
    _this.controller.OnConnectClose = () => {
      console.log('【Lynn】退出房间 OnConnectClose')
      _this.callback('OnConnectClose')
      // 自定义逻辑
    }

    /**
     * 退出房间
     * @param participant 退出者 ID
     * @param exitType 1：正常退出 2：异常退出
     * @constructor
     */
    _this.controller.OnParticipantLeaveRoom = (participant, exitType) => {
      console.log('【Lynn】退出房间', participant, exitType)
      _this.callback('OnParticipantLeaveRoom', { participant, exitType })
      // 自定义逻辑
    }
  }

  /**
   * 所有失败的监听回调
   */
  onListeningFailedMethod() {
    let _this = this

    /**
     * 连接失败
     * @param err_code
     * @param err_msg
     * @constructor
     */
    _this.controller.OnConnectFailed = (err_code, err_msg) => {
      console.error('【Lynn】连接失败', err_code, err_msg)
    }

    /**
     * 订阅媒体流失败
     * @param sid 流 ID
     * @param err_code
     * -1081：服务器返回错误
     * -1082：视频窗口的 subscribe_video_id 已使用
     * -1083：超出订阅限额
     * -1084：订阅建立媒体链路失败
     * -1085：订阅的窗口 subscribe_video_id 为空
     * @param err_msg 状态信息
     * @constructor
     */
    _this.controller.OnSubscribeFailed = (sid, err_code, err_msg) => {
      console.error('【Lynn】订阅媒体流失败', sid, err_code, err_msg)
    }

    /**
     * 初始化房间失败
     * @param err_code
     * -201：房间状态错误
     * -202：参数错误
     * -204：E2EE_ikm 为空
     * -205：自定义分辨率、帧率、码率参数未提供。
     * @param err_msg 状态信息
     * @constructor
     */
    _this.controller.OnInitRoomConfigFail = (err_code, err_msg) => {
      console.error('【Lynn】初始化房间失败', err_code, err_msg)
    }

    /**
     * 加入房间失败
     * @param err_code
     * -401：房间未初始化
     * -402：参数错误
     * -403：服务器返回错误
     * -404：加入房间超时
     * @param err_msg 状态信息
     * @constructor
     */
    _this.controller.OnJoinRoomFailed = (err_code, err_msg) => {
      console.error('【Lynn】加入房间失败', err_code, err_msg)
    }

    /**
     * 发送文本消息失败
     * @param msgId 消息 ID
     * @param code 10291（错误码）：服务端返回错误
     * @param msg 消息文本
     * @constructor
     */
    _this.controller.OnSendTextMsgFailed = (msgId, code, msg) => {
      console.error('【Lynn】发送文本消息失败', msgId, code, msg)
    }
  }

  /**
   * 监听连接成功
   * @param params
   */
  async onConnect() {
    let _this = this
    await _this.onListeningSuccessMethod()
    await _this.onListeningFailedMethod()
    let connectParams = {
      sign: this.sign,
      biz_name: this.bizName,
      sub_biz: this.subBiz,
      uid: this.userId,
      room_server_url: this.room_server_url
    }
    _this.controller.Connect(connectParams);// 监听连接成功
  }

  onSendTextMsg(msg) {
    let _this = this
    /**
     * 发送文本消息。
     * @param msg 消息文本
     * @param participants 发送目标 ID，为空则发给与会其他所有人
     */
    console.log('【Lynn】发送文本消息', { msg, participants: _this.participants })
    _this.controller.SendTextMsg({
      msg,
      participants: _this.participants
    })
  }

  onSendData(msg) {
    let _this = this
    /**
     * 发送图片消息。
     * @param msg 消息文本
     */
    console.log('【Lynn】发送图片消息', msg)
    _this.controller.SendData(msg)
  }

  OnRoomAttendanceList(config) {
    let _this = this
    /**
     * 房间信息监听 推送“房间与会者列表”给新加入者。
     * @param participants
     * uid String 房间与会者的 UID
     * userType int 与会者的用户类型： 0：普通用户 101：rtcvod 点播服务器
     * publish jsonarray 发布流
     * feedId String 房间与会者的发布流 ID
     * tag String feedId 对应的 tag
     * @constructor
     */
    _this.controller.OnRoomAttendanceList = (participants: IParticipants) => {
      console.log('【Lynn】房间信息监听', participants);
      this.participants = participants;
      (participants || []).forEach((element: any) => {
        const { publish } = element
        if (publish?.[0]?.tag !== '__mij_avatar_mij__') {
          _this.feedId = publish?.[0]?.feedId;
          _this.controller.Subscribe({
            ...config,
            feedId: publish?.[0]?.feedId,// feedId
          })
        } else {
          _this.feedId = publish?.[0]?.feedId;
        }
      })
    }
  }

  OnReceiveTextMsg() {
    let _this = this
    /**
     * 下发文本消息
     * @param uid
     * @param msg
     * @constructor
     */
    _this.controller.OnReceiveTextMsg = (uid: number, msg: string) => {
      const receiveData: ReceiveData = JSON.parse(msg)
      console.log('【Lynn===】OnReceiveTextMsg==>receiveData', receiveData)
      _this.buildMessage(receiveData)
    }
  }

  // 处理消息
  buildMessage(receiveData: ReceiveData) {
    if (receiveData.command == 'feedText') {
      const { text } = JSON.parse(receiveData.data)
      this.callback('feedText', JSON.parse(text))
      console.log('【Lynn】下发文本消息 feedText', JSON.parse(text))
      return;
    }
    if (receiveData.command == 'subtitle') {
      console.log('【Lynn===】下发文本消息 subtitle', receiveData)
      this.callback('subtitle', receiveData)
      return;
    }
    if (receiveData.asrChange) {
      this.callback('asrChange', receiveData)
      console.log('【Lynn===】下发文本消息 asrChange===>消息流式输出', receiveData.asrChange)
      return
    }
    if (receiveData.asrEnd) {
      this.callback('asrEnd', receiveData)
      console.log('【Lynn===】下发文本消息 asrEnd===>消息输出完成，注意：关闭mRtc麦克风收声', receiveData.asrEnd)
      return
    }
    /*if (receiveData.subtitle) {
      console.log('【Lynn】下发文本消息 接收下发文本内容===>subtitle', receiveData.subtitle)
      return
    }*/
    if (receiveData.imageParseStatus) {
      this.callback('imageParseStatus', receiveData)
      console.log('【Lynn】下发文本消息 处理播放内容展示===>receiveData.imageParseStatus', receiveData.imageParseStatus)
      return
    }
    // console.log('【Lynn===】下发文本消息 ========buildMessage', receiveData)
    // receiveData.asrChange 消息流式输出
    // receiveData.asrEnd 消息输出完成，注意：关闭mRtc麦克风收声
    // receiveData.subtitle 接收下发文本内容
    // receiveData.executeType = callbackAction 处理播放内容展示
    // console.log('【Lynn】下发文本消息 ========结束')
  }

  // DataChannel消息
  OnReceiveData() {
    let _this = this
    /**
     * 接收 Channel 数据
     * @param data
     * @constructor
     */
    _this.controller.OnReceiveData = (data: string) => {
      const receiveData: ReceiveData = JSON.parse(data)
      console.log('【Lynn】接收 Channel 数据', data, receiveData)
      // 参考下方播报逻辑
    }
  }

  onTurnOnTheMicrophone(enabled) {
    const _this = this
    console.log('【Lynn===publishSid】', _this.publishSid)
    console.log(`【Lynn】${enabled === 1 ? '开启' : '关闭'}本地麦克风`, enabled)
    _this.controller.SetLocalAudioEnable(enabled, _this.publishSid)
  }

  onTurnOnTheCamera(enabled) {
    const _this = this
    console.log('【Lynn===publishSid】', _this.publishSid)
    console.log(`【Lynn===enabled】${enabled === 1 ? '开启' : '关闭'}摄像头`, enabled)
    _this.controller.SetLocalVideoEnable(enabled, _this.publishSid)
  }

  onLeaveRoom() {
    let _this = this
    _this.controller.Disconnect()

  }

  // DataChannel消息
  OnHandleReceiveData(data: ReceiveData) {
    const receiveData: ReceiveData = JSON.parse(data)

    // receiveData.fileUpload 处理图片上传信息

    // receiveData.imageParseStatus 图片解析结果

    // receiveData.text
    this.buildMessage(JSON.parse(receiveData.text))

    // receiveData.command = 'feedText'
    const { text } = JSON.parse(receiveData.data)
    this.buildMessage(JSON.parse(text))

    // receiveData.command != 'feedText'
    this.buildMessage(receiveData)
  }
  /*
      // 普通文本消息
      OnReceiveTextMsg(uid: number, data: string) {
          const receiveData: ReceiveData = JSON.parse(data)
           this.buildMessage(receiveData)
      }
      */

















}

