<template>
	<view class="container" data-type="template" data-is="1v1" data-attr="pusher, streamList, debug">
    <view v-for="item in streams.slice(0,1)" :key="item.streamID" class="player-container" :style="'display:'+playerStyle">
      <template v-if="item.src && (item.hasVideo || item.hasAudio)">
        <live-player
          class="player"
          :data-userid="item.userID"
          :data-streamid="item.streamID"
          :data-streamtype="item.streamType"
          :src="item.src"
          mode="RTC"
          :autoplay="item.autoplay"
          :mute-audio="item.muteAudio"
          :mute-video="item.muteVideo"
          :orientation="item.orientation"
          :object-fit="item.objectFit"
          :background-mute="item.enableBackgroundMute"
          :min-cache="item.minCache"
          :max-cache="item.maxCache"
          :sound-mode="item.soundMode"
          :enable-recv-message="item.enableRecvMessage"
          :auto-pause-if-navigate="item.autoPauseIfNavigate"
          :auto-pause-if-open-native="item.autoPauseIfOpenNative"
          :debug="debug"
          @statechange="playerStateChangeFun"
          @fullscreenchange="playerFullscreenChangeFun"
          @netstatus="playerNetStatusFun"
          @audiovolumenotify="playerAudioVolumeNotifyFun"
          :idAttr="item.streamID" />
      </template>
    </view>
    <view class="pusher-container" :style="'display:'+pusherStyle">
      <live-pusher
        class="pusher"
        :url="pusher.url"
        :mode="pusher.mode"
        :autopush="pusher.autopush"
        :enable-camera="pusher.enableCamera"
        :enable-mic="pusher.enableMic"
        :enable-agc="pusher.enableAgc"
        :enable-ans="pusher.enableAns"
        :enable-ear-monitor="pusher.enableEarMonitor"
        :auto-focus="pusher.enableAutoFocus"
        :zoom="pusher.enableZoom"
        :min-bitrate="pusher.minBitrate"
        :max-bitrate="pusher.maxBitrate"
        :video-width="pusher.videoWidth"
        :video-height="pusher.videoHeight"
        :beauty="pusher.beautyLevel"
        :whiteness="pusher.whitenessLevel"
        :orientation="pusher.videoOrientation"
        :aspect="pusher.videoAspect"
        :device-position="pusher.frontCamera"
        :remote-mirror="pusher.enableRemoteMirror"
        :local-mirror="pusher.localMirror"
        :background-mute="pusher.enableBackgroundMute"
        :audio-quality="pusher.audioQuality"
        :audio-volume-type="pusher.audioVolumeType"
        :audio-reverb-type="pusher.audioReverbType"
        :waiting-image="pusher.waitingImage"
        :debug="debug"
        @statechange="pusherStateChangeHandlerFun"
        @netstatus="pusherNetStatusHandlerFun"
        @error="pusherErrorHandlerFun"
        @bgmstart="pusherBGMStartHandlerFun"
        @bgmprogress="pusherBGMProgressHandlerFun"
        @bgmcomplete="pusherBGMCompleteHandlerFun" />
    </view>
  </view>
</template>

<script>
export default {
  name: 'jhlive-wechat',
	data() {
		return {
      pusher: null,
      users: [],
		};
	},

	props: {
		sdkAppID: Number,
    userSig: String,
    userid: String,
    roomid: String, 
    isAuthor: Boolean,
    linkMic: Boolean
  },
  computed: {
    streams() {
      console.log('--users', this.users);
      let streams = [];
      this.users.forEach(v=>{
        let userStreams = Object.entries(v.streams);
        streams = streams.concat(userStreams.map(([kk,vv])=>vv).filter(vv=>vv.hasVideo));
      });
      console.log('--streams', streams);
      return streams;
    },
    playerStyle() {
      return (!this.isAuthor)?'block':'none';
    },
    pusherStyle() {
      return this.isAuthor?'block':'none';
    }
  },
	methods: {
    enterRoom() {
      this.pusher = {
        url: 'room://cloud.tencent.com/rtc?sdkappid=' +
        this.sdkAppID +
        '&roomid=' +
        this.roomid +
        '&userid=' +
        this.userid +
        '&usersig=' +
        this.userSig +
        '&appscene=' +
        'live' +
        '&encsmall=' +
        '1' +
        '&cloudenv=' +
        'PRO',
        mode: 'RTC', // RTC：实时通话（trtc sdk） live：直播模式（liteav sdk）
        autopush: this.isAuthor||this.linkMic, // 自动推送
        enableCamera: this.isAuthor, // 是否开启摄像头
        enableMic: this.isAuthor||this.linkMic, // 是否开启麦克风
        enableAgc: false, // 是否开启音频自动增益
        enableAns: false, // 是否开启音频噪声抑制
        enableEarMonitor: false, // 是否开启耳返（目前只在iOS平台有效）
        enableAutoFocus: true, // 是否自动对焦
        enableZoom: false, // 是否支持调整焦距
        minBitrate: 200, // 最小码率
        maxBitrate: 1000, // 最大码率
        videoWidth: 360, // 视频宽（若设置了视频宽高就会忽略aspect）
        videoHeight: 640, // 视频高（若设置了视频宽高就会忽略aspect）
        beautyLevel: 0, // 美颜，取值范围 0-9 ，0 表示关闭
        whitenessLevel: 0, // 美白，取值范围 0-9 ，0 表示关闭
        videoOrientation: 'vertical', // vertical horizontal
        videoAspect: '9:16', // 宽高比，可选值有 3:4,9:16
        frontCamera: 'front', // 前置或后置摄像头，可选值：front，back
        enableRemoteMirror: false, // 设置推流画面是否镜像，产生的效果会表现在 live-player
        localMirror: 'auto', // auto:前置摄像头镜像，后置摄像头不镜像（系统相机的表现）enable:前置摄像头和后置摄像头都镜像 disable: 前置摄像头和后置摄像头都不镜像
        enableBackgroundMute: false, // 进入后台时是否静音
        audioQuality: 'high', // 高音质(48KHz)或低音质(16KHz)，可选值：high，low
        audioVolumeType: 'voicecall', // 声音类型 可选值： media: 媒体音量，voicecall: 通话音量
        audioReverbType: 0, // 音频混响类型 0: 关闭 1: KTV 2: 小房间 3:大会堂 4:低沉 5:洪亮 6:金属声 7:磁性
        waitingImage: '', // 当微信切到后台时的垫片图片 trtc暂不支持
        waitingImageHash: ''
      };

      console.log('JHLIVE-PUSHER CONFIG', this.pusher);
      setTimeout(()=>{
        this.pusherContext = wx.createLivePusherContext();
        this.pusherContext.start();
        console.log('JHLIVE-PUSHER pusherContext', this.pusherContext);
      },1000);
		},
		exitRoom: function() {
			if (this.pusherContext) {
        this.pusherContext.stop();
        this.pusherContext = null;
      }
    },
    /** --- pusher event handler --- **/
		pusherStateChangeHandlerFun: function(event) {
			const code = event.detail.code;
      const message = event.detail.message;
      
			switch (code) {
				case 0:
					console.log(message, code);
					break;

				case 1001:
					console.log('已经连接推流服务器', code);
					break;

				case 1002:
					console.log('已经与服务器握手完毕,开始推流', code);
					break;

				case 1003:
					console.log('打开摄像头成功', code);
					break;

				case 1004:
					console.log('录屏启动成功', code);
					break;

				case 1005:
					console.log('推流动态调整分辨率', code);
					break;

				case 1006:
					console.log('推流动态调整码率', code);
					break;

				case 1007:
					console.log('首帧画面采集完成', code);
					break;

				case 1008:
					console.log('编码器启动', code);
					break;

				case 1018:
					console.log('进房成功', code);
					break;

				case 1019:
					console.log('退出房间', code);
					break;

				case 2003:
					console.log('渲染首帧视频', code);
					break;

				case 1020: // 远端用户全量列表更新
          break;
        case 1031: {// 远端用户进房通知
          const data = JSON.parse(event.detail.message)||{};
          console.log('远端用户进房通知', data);
          (data.userlist||[]).forEach( v=> {
            if(!this.users.find(vv => vv.userid == v.userid)) {
              this.users.push({
                userid: v.userid,
                streams: {},
              });
            }
          })
        }break;
        case 1032: {// 远端用户退房通知
          console.log('远端用户退房通知', data);
          const data = JSON.parse(event.detail.message)||{};
          (data.userlist||[]).forEach( v=> {
            let user = this.users.find(v => v.userid == data.userid);
            if(!user) return;
            user.streams.forEach(vv=>{
              if(vv.playerContext) {
                vv.playerContext.stop;
                vv.playerContext = null;
              }
            });
            user.streams = [];
          })
          this.users = this.users.filter(v => (data.userlist||[]).find(vv=>vv.userid!=v.userid));
        }break;
        case 1033: {// 用户视频状态变化，新增stream或者更新stream 状态
          console.log('用户视频状态变化，新增stream或者更新stream', data);
          const data = JSON.parse(event.detail.message)||{};
          (data.userlist||[]).forEach( v=> {
            let user = this.users.find(vv => v.userid == v.userid);
            if(!user) return;
              let stream = user.streams[v.streamtype] = user.streams[v.streamtype] || {
              streamType: v.streamtype,
              src: '',
              mode: 'RTC',
              autoplay: true, // 7.0.9 必须设置为true，否则 Android 有概率调用play()失败
              muteAudio: false, // 默认不拉取音频，需要手动订阅
              muteVideo: false, // 默认不拉取视频，需要手动订阅
              orientation: 'vertical', // 画面方向 vertical horizontal
              objectFit: 'fillCrop', // 填充模式，可选值有 contain，fillCrop
              enableBackgroundMute: false, // 进入后台时是否静音（已废弃，默认退台静音）
              minCache: 1, // 最小缓冲区，单位s（RTC 模式推荐 0.2s）
              maxCache: 2, // 最大缓冲区，单位s（RTC 模式推荐 0.8s）
              soundMode: 'speaker', // 声音输出方式 ear speaker
              enableRecvMessage: 'false', // 是否接收SEI消息
              autoPauseIfNavigate: true, // 当跳转到其它小程序页面时，是否自动暂停本页面的实时音视频播放
              autoPauseIfOpenNative: true // 当跳转到其它微信原生页面时，是否自动暂停本页面的实时音视频播放
            }

            stream.userID = v.userid;
            stream.streamID = v.userid + '_' + stream.streamType;
            stream.hasVideo = v.hasvideo;
            stream[`has${stream.streamType}Video`] = stream.hasVideo;
            stream.src = v.playurl;
            // stream.objectFit = stream.hasVideo && stream.streamType === 'aux' && 'contain';

            if(stream.hasVideo) stream.playerContext = wx.createLivePlayerContext(stream.streamID, this);
          })
          this.users = [...this.users];
        }break;
        case 1034: {// 远端用户音频状态位变化通知
          console.log('远端用户音频状态位变化通知', data);
          const data = JSON.parse(event.detail.message)||{};
          (data.userlist||[]).forEach( v=> {
            let user = this.users.find(vv => v.userid == vv.userid);
            if(!user) return;
            
            v.streamtype = 'main';
            let stream = user.streams[v.streamtype] = user.streams[v.streamtype] || {
              streamType: v.streamtype,
              src: '',
              mode: 'RTC',
              autoplay: true, // 7.0.9 必须设置为true，否则 Android 有概率调用play()失败
              muteAudio: false, // 默认不拉取音频，需要手动订阅
              muteVideo: false, // 默认不拉取视频，需要手动订阅
              orientation: 'vertical', // 画面方向 vertical horizontal
              objectFit: 'fillCrop', // 填充模式，可选值有 contain，fillCrop
              enableBackgroundMute: false, // 进入后台时是否静音（已废弃，默认退台静音）
              minCache: 1, // 最小缓冲区，单位s（RTC 模式推荐 0.2s）
              maxCache: 2, // 最大缓冲区，单位s（RTC 模式推荐 0.8s）
              soundMode: 'speaker', // 声音输出方式 ear speaker
              enableRecvMessage: 'false', // 是否接收SEI消息
              autoPauseIfNavigate: true, // 当跳转到其它小程序页面时，是否自动暂停本页面的实时音视频播放
              autoPauseIfOpenNative: true // 当跳转到其它微信原生页面时，是否自动暂停本页面的实时音视频播放
            }

            stream.userID = v.userid;
            stream.streamID = v.userid + '_' + stream.streamType;
            stream.hasAudio = v.hasaudio;
            stream[`has${stream.streamType}Audio`] = stream.hasAudio;
            stream.src = v.playurl;

            if(stream.hasAudio) stream.playerContext = wx.createLivePlayerContext(stream.streamID, this);
          })
          this.users = [...this.users];
        }break;
				case -1301:
					console.error('打开摄像头失败: ', code);
					break;

				case -1302:
					console.error('打开麦克风失败: ', code);
					break;

				case -1303:
					console.error('视频编码失败: ', code);
					break;

				case -1304:
					console.error('音频编码失败: ', code);
					break;

				case -1307:
					console.error('推流连接断开: ', code);
					break;

				case -100018:
					console.error('进房失败: ', code, message);
					break;

				case 5000:
					console.log('小程序被挂起: ', code); 
          this.exitRoom()
          this.enterRoom()
					break;

				case 1021:
					console.log('网络类型发生变化，需要重新进房', code);
					break;

				case 2007:
					console.log('本地视频播放loading: ', code);
					break;

				case 2004:
					console.log('本地视频播放开始: ', code);
					break;

				default:
					console.log(message, code);
			}
		},
		pusherNetStatusHandlerFun: function(event) {
			
		},
		pusherErrorHandlerFun: function(event) {
			try {
        console.error('pusher error: ');
				const code = event.detail.errCode;
				const message = event.detail.errMsg;
        console.error(code, message);
			} catch (exception) {}
		},
		pusherBGMStartHandlerFun: function(event) {
			
		},
		pusherBGMProgressHandlerFun: function(event) {
			
		},
		pusherBGMCompleteHandlerFun: function(event) {
			
    },
    
    /** --- player event handler --- **/
		playerStateChangeFun: function(event) {
      console.log('playerStateChangeFun');
		},
		playerFullscreenChangeFun: function(event) {
      console.log('playerFullscreenChangeFun');
		},
		playerNetStatusFun: function(event) {
      console.log('playerNetStatusFun');
      let dataset = event.currentTarget.dataset;
      let info = event.detail.info;
      let user = this.users.find(v => v.userid == dataset.userid);
      if(!user) return;
      let stream = user.streams[dataset.streamtype];
      if(!stream) return;
      stream.videoWidth = info.videoWidth;
      stream.videoHeight = info.videoHeight;
		},
		playerAudioVolumeNotifyFun: function(event) {
      console.log('playerAudioVolumeNotifyFun');
		},
	}
};
</script>

<style lang="less" scoped>
.container {
  width: 100%;
  height: 100%;
}
.pusher-container {
  width: 100%;
  height: 100%;
}
.player-container{
  width: 100%;
  height: 100%;
}
.pusher {
  width: 100%;
  height: 100%;
}
.player {
  width: 100%;
  height: 100%;
}

</style>
