var serverURL = "avd.nice2meet.cn:9631";  // 媒体服务器地址，https访问请将端口号改为9630
var accessKey = 'demo_access';
var secretKey = 'demo_secret';

var accessToken = null;

var room = null;
var roomId = null;
var userId = Math.uuid();
var userName = 'user' + parseInt(Math.floor(Math.random() * 9000) + 1000);
var AVDEngine = ModuleBase.use(ModulesEnum.avdEngine);
var avdEngine = new AVDEngine();

// avdEngine.setLog(Appender.browserConsole, LogLevel.debug);
avdEngine.initDevice().then(initDeviceSuccess);
avdEngine.checkDevice().then(checkResult).otherwise(checkError);
// 设置视频编码格式默认VP8
// avdEngine.setVideoCoding(VideoCodingType.VP8);
var restApi = new RestApi(serverURL);

var isRoomOwer = false;
var self = this;

var localVideo = document.getElementById("localVideo");
var remoteAudio = document.getElementById("remoteAudio");
var remoteVideo = document.getElementById("remoteVideo");
var local_video = document.getElementById("local_video");
var local_audio = document.getElementById("local_audio");
var remote_video = document.getElementById("remote_video");
var remote_audio = document.getElementById("remote_audio");

var localVideoId = '';
var localAudioId = '';
var isOpenVideoShow = true;
var isOpenAudioShow = true;

var isVideoFacility = false
var isAudioFacility = false

restApi.getAccessToken(accessKey, secretKey).then((res) => {
    console.log('Success', res)
    self.accessToken = res.token;
}).otherwise((error) => {
    console.log("Error", error);
    $(".promptMsg").html('getAccessToken(),error:' + error.msg);

})

function checkResult(result) {
    isVideoFacility = result.video;
    isAudioFacility = result.audio;
}

function checkError(error) {
    $(".promptMsg").html("get device error!error code:" + error.code + "; error message:" + error.message);
}

//创建房间
function createRoom() {
    var topic = 'testingMeeting';
    /**
     * @desc 创建房间
     * @param {String} - token
     * @param {String} - 会议主题
     * @param {String} - 用户id
     */
    restApi.createRoom(self.accessToken, topic, self.userId).then((res) => {
        console.log('Success', res)
        $("#first").val(res.room_id);
    }).otherwise((error) => {
        console.log("Error", error)
        $(".promptMsg").html('createRoom(),error:' + error.msg);
    })
}

//  加入会议
function joinRoom() {
    if (room) { return }
    if (!isVideoFacility) {
        $('.promptMsg').html('没有摄像头设备，请插入');
    } else if (!isAudioFacility) {
        $('.promptMsg').html('没有音频设备，请插入');
    } else if ($("#first").val() == '') {
        $('.promptMsg').html('会议号不能为空，请先创建房间');
    } else {
        self.roomId = $("#first").val();
        // 初始化
        avdEngine.init(self.serverURL, self.accessToken).then(initSuccess).otherwise(initError);
    }
}

function initDeviceSuccess(state) {
    if(state && state === 1){
        console.log('+++initDevice success')
    }
}

function initSuccess() {
    // 传入房间号获取房间对象。如房间存在,直接返回，不存在时创建房间后返回
    room = avdEngine.obtainRoom(self.roomId);
    room.join(self.userId, self.userName, '', null).then(joinSuccess).otherwise(joinError);
}

function initError(error) {
    $(".promptMsg").html("AVDEngine 初始化失败！initError(),error:" + error.message);
}

function joinSuccess() {
    console.log('加入会议成功');
    // avc模式混屏情况下，web端进行混屏布局操作的用户其user_agent指定值
    // room.setUserAgent(USER_AGENT_AVD_MEDIA_MIXER_ADMIN);
    //  自动打开音视频
    openCamera();
    openMicrophone();

    registerRoomCallback();

    //加会登陆前，会议中已经发布的视频资源,采取订阅处理
    onPublishCameraNotify(room.pubVideos);

    // 处理房间内的参会者，给每个参会者添加回调事件
    participantsHandle(room.getParticipants());

    $('.localVideo_userName').html(self.userName);
}

function joinError(error) {
    console.log('==================joinError(),error:', error)
    if (error.code == 404) {
        $(".promptMsg").html("加会失败！原因房间没有找到，请核实。joinError(),error");
    } else {
        $(".promptMsg").html('joinError(),error:' + error.message + "[" + error.code + "]");
    }
}

function openCamera() {
    if (isOpenVideoShow) {
        isOpenVideoShow = false;
        videos = room.selfUser.videos;
        if (videos && videos.length > 0) {
            var video = videos[0];
            if (video) {
                localVideoId = video.id;
                video.previewAndPublish(localVideo).otherwise(showError);
                local_video.className = 'openCamera';
            }
        }
    }
}

function closeCamera() {
    if (!isOpenVideoShow) {
        isOpenVideoShow = true;
        var video = room.selfUser.getVideo(self.localVideoId);
        if (video) {
            local_video.className = 'closeCamera';
            video.unpreview();
            video.unpublish();
        }
    }
}

function openMicrophone() {
    if (isOpenAudioShow) {
        isOpenAudioShow = false;
        // 获取audio对象
        var audio = room.selfUser.audio;
        localAudioId = audio.id;
        if (audio) {
            audio.openMicrophone().otherwise(showError);
            local_audio.className = 'openMicrophone';
        }
    }
}

function closeMicrophone() {
    if (!isOpenAudioShow) {
        isOpenAudioShow = true;
        var audio = room.selfUser.getAudio(self.localAudioId);
        if (audio) {
            local_audio.className = 'closeMicrophone';
            audio.closeMicrophone();
        }
    }
}

function showError(error) {
    $(".promptMsg").html('showError(),error:' + error.message + "[" + error.code + "]");
}

function leaveRoom() {
    if (!room) { return }
    var close = window.confirm('您确认退出会议?');
    if (close) {
        var reason = 1; //退会原因
        /**
         * @desc 退出会议
         * @param {int} reason - 退会原因
         * @param {boolean} kickoffOpt - 退会类型： true:被踢退会，false:主动退会，可以不填
         */
        room.leave(reason).then(function () {
            top.location = "index.html";
            return false;
        });
    }
}

function registerRoomCallback() {
    room.addCallback(RoomCallback.connection_status, onConnectionStatus);
    room.addCallback(RoomCallback.user_join_notify, onUserJoinNotify);
    room.addCallback(RoomCallback.user_leave_notify, onUserLeaveNotify);
	room.addCallback(RoomCallback.leave_indication, onLeaveIndication);
	
	room.addCallback(RoomCallback.close_room_result, onCloseRoomResult);
	room.addCallback(RoomCallback.close_room_notify, onCloseRoomNotify);
	
    room.addCallback(RoomCallback.mcu_peerconnection_completed, onMCUPeerConnectionCompleted);
    room.addCallback(RoomCallback.connection_indicator,onConnectionIndicator);
}
function onMCUPeerConnectionCompleted() {
    console.log('+++开始收集网络情况...');
    room.connectionInfoCollector.start(); //开始收集网络情况,不填写频率参数，默认1000毫秒
    //room.connectionInfoCollector.stop();  //停止收集网络情况
}

/**
 * //房间级别
    roomConnection.localAddress   本地地址
    roomConnection.localPort      本地端口
    roomConnection.localProtocol  本地协议
    roomConnection.remoteAddress  远端地址
    roomConnection.remotePort     远端端口
    roomConnection.remoteProtocol  远端协议
    roomConnection.downloadBitrate  下载流量
    roomConnection.uploadBitrate    上传流量
    roomConnection.downloadPacket  下载数据包
    roomConnection.uploadPacket    上传数据包
    roomConnection.downloadPacketLost  下载数据包丢包数
    roomConnection.uploadPacketLost   上传数据包丢包数
    roomConnection.downloadPacketLossRate  下载数据包丢包率
    roomConnection.uploadPacketLossRate   上传数据包丢包率

    //某路音频相关
    var audioConnection = connectionIndicator.getAudioConnection(userId);
    audioConnection.downloadBitrate   音频下载流量
    audioConnection.uploadBitrate     音频上传流量
    audioConnection.downloadPacket   音频下载数据包
    audioConnection.uploadPacket     音频上传数据包
    audioConnection.packetsLost     音频数据包丢包数
    audioConnection.ssrc
    audioConnection.trackId
    audioConnection.payloadType
    audioConnection.mimeType
    audioConnection.clockRate

    //某路视频相关
    videoConnection = connectionIndicator.getVideoConnection(userId, cameraId);
    videoConnection.downloadBitrate   视频下载流量
    videoConnection.uploadBitrate     视频上传流量
    videoConnection.downloadPacket    视频下载数据包
    videoConnection.uploadPacket     视频传数据包
    videoConnection.packetsLost     视频数据包丢包数
    videoConnection.resolution        分辨率
    videoConnection.frameRate         帧率
    videoConnection.ssrc
    videoConnection.trackId
    videoConnection.payloadType
    videoConnection.mimeType
    videoConnection.clockRate

    //某路桌面共享相关
    screenConnection = connectionIndicator.getScreenConnection(userId);
    screenConnection.downloadBitrate   桌面共享下载流量
    screenConnection.uploadBitrate     桌面共享上传流量
    screenConnection.downloadPacket    桌面共享下载数据包
    screenConnection.uploadPacket     桌面共享传数据包
    screenConnection.packetsLost      桌面共享数据包丢包数
    screenConnection.resolution        分辨率
    screenConnection.frameRate         帧率
    screenConnection.ssrc
    screenConnection.trackId
    screenConnection.payloadType
    screenConnection.mimeType
    screenConnection.clockRate
 * @param {object} connectionIndicator 连接指示器
 */
function onConnectionIndicator(connectionIndicator){
    if(connectionIndicator){
        // var roomConnection = connectionIndicator.getRoomConnection();
    }
}

/**
 * @desc 网络状态回调
 * @param status - 状态码
 */
function onConnectionStatus(status) {
    if(status == ConnectionStatus.connecting) {
		$(".promptMsg").html("网络故障,正在与服务器重连中...");
	} else if(status == ConnectionStatus.connected) {
		//连接成功
		$(".promptMsg").html("");
	} else if(status == ConnectionStatus.reJoinConnected) {
		//重新加会成功
		$(".promptMsg").html("");
	} else if(status == ConnectionStatus.reconnected) {
		//重连接成功
		$(".promptMsg").html("");
	} else if(status == ConnectionStatus.connectFailed) {
		$(".promptMsg").html("网络故障,与服务器重连超时，正在重新加会操作中...");

		//应用层清场
		if(room.connectionInfoCollector) {
			room.connectionInfoCollector.stop(); //停止收集网络情况
		}
	} else if(status == ConnectionStatus.reJoinRoomTimeOut) {
		$(".promptMsg").html("网络故障,重新加会中...");
        /**
         * @desc 多次后重新加会超时后，开启持续永久重新加会
         */
	    room.continuousReJoin();
	}
}

/**
 * @desc 参会者加会回调
 * @param {Object} users － 参会者数组
 */
function onUserJoinNotify(users) {
    console.log("============onUserJoinNotify(),users:", users);
    participantsHandle(users);
}

/**
 * @desc 参会者退会回调
 * @param {int} opt - 退会类型
 * @param {int} reason  - 退会原因
 * @param {Object} user - 退会用户
 */
function onUserLeaveNotify(opt, reason, user) {
    //UDP媒体通道建立超时807错误
    if(reason == 807) {
        if(user.id == room.selfUser.id){
            $(".promptMsg").html("本端 807错误,UDP不通或UDP媒体通道建立超时!").show();
        }else {
            $(".promptMsg").html(user.name +" 807错误,UDP不通或UDP媒体通道建立超时!").show();
        }
        return;
    }
	if(reason == 812){ //用户心跳超时掉线（如异常退会）
	    $(".promptMsg").html(user.name+" 已异常退会").show();
	}else{
		$(".promptMsg").html(user.name+" 已退会").show();
	}

    $('.remoteVideo_userName').html('');
    remote_video.className = '';
    remote_audio.className = '';
}


/**
 * @desc 关闭会议回调结果
 * @param {int} result - 关闭结果
 * @param {String} description - 描述
 */
function onCloseRoomResult(result, description) {
	console.log("+++onCloseRoomResult(),result:"+result+",description:"+description);
	if(result == 0) {
		console.log("关闭会议成功");
		top.location = "index.html";
		return false;
    }
}


/**
 * @desc 被踢出会议室
 * @param {Object} reason - 被踢原因
 * @param {Object} userId - 踢人的操作者
 */
function onLeaveIndication(reason, userId) {
	console.log("+++onLeaveIndication(),reason:" + reason + ",userId:" + userId);
	if(reason == 804) {
		//同一个userid加会， 把前一个人踢下线
		 $(".promptMsg").html("你已在另一个地方登陆，被踢出会议室。被踢原因：" + reason).show();
	} else if(reason == 808) {
		//调用Restful接口把人踢下线或SDK调踢人接口通知会议中的第三方用户
		 $(".promptMsg").html("你被" + userId + "踢出会议室。被踢原因：" + reason).show();
	} else {
		 $(".promptMsg").html("你被" + userId + "踢出会议室。被踢原因：" + reason).show();
	}
	
	top.location = "index.html";
	return false;
}


/**
 * @desc 收到关闭房间通知，退出会议操作
 * @param {int} roomId - 房间ID
 * @param {int} reason  -关闭会议原因
 */
function onCloseRoomNotify(roomId, reason) {
	console.log("+++onCloseRoomNotify(),roomId:"+roomId+",reason:"+reason);
	
	var tips = "";
	if(reason == 809) {
		tips = "服务没有授权用户入会(最多2个用户),超过15分钟服务器主动关闭房间强制踢人";
	}else if(reason == 810) {
		tips = "SDK调用接口关闭会议";
	}else if(reason == 811){
		tips = "服务更新维护时关闭会议";
	}else if(reason == 815){
		tips = "调用restful接口关闭会议";
	}	
	
	$(".promptMsg").html("会议已关闭。原因:" + tips).show();

	setTimeout(function() {
		top.location = "index.html";
		return false;
	}, 2000);
}



/**
 * @desc  用户回调事件
 * @param {Object} participants - 用户集数组
 */
function participantsHandle(participants) {
    participants.forEach(function (user) {
        user.addCallback(UserCallback.camera_status_notify, onCameraStatusNotify);
        user.addCallback(UserCallback.microphone_status_notify, onMicrophoneStatusNotify);

        user.addCallback(UserCallback.publish_camera_notify, onPublishCameraNotify);
        user.addCallback(UserCallback.unpublish_camera_notify, onUnpublishCameraNotify);
        user.addCallback(UserCallback.subscrible_camera_result, onSubscribleCameraResult);
        user.addCallback(UserCallback.unsubscrible_camera_result, onUnsubscribleCameraResult);

        user.addCallback(UserCallback.subscrible_microphone_result, onSubscribleMicrophoneResult);
        user.addCallback(UserCallback.unsubscrible_microphone_result, onUnsubscribleMicrophoneResult);
    })
}

/**
 * 麦克风状态更新
 * @param {Object} status － 状态
 * @param {Object} microphoneId － 麦克风设备Id 
 * @param {Object} microphoneName － 麦克风设备名称
 * @param {Object} userId － 麦克风设备所属者ＩＤ
 */
function onMicrophoneStatusNotify(status, microphoneId, microphoneName, userId) {
    if (userId == room.selfUser.id) {
        if (status == StreamStatus.published) {
            local_audio.className = 'openMicrophone';
        } else if (status == StreamStatus.init) {
            local_audio.className = 'closeMicrophone';
        }
    } else {
        if (status == StreamStatus.published) {
            remote_audio.className = 'openMicrophone';
        } else if (status == StreamStatus.init) {
            remote_audio.className = 'closeMicrophone';
        }
    }
}

/**
 * 房间中发布的视频回调
 * @param {Object} video-发布视频集
 */
function onUnpublishCameraNotify(video) {
    video.unsubscrible();
}

/**
 * 摄像头状态更新
 * @param {Object} status － 状态
 * @param {Object} cameraId － 摄像头设备Id
 * @param {Object} cameraName－ 摄像头设备名称
 * @param {Object} userId－ 摄像头设备所属者ＩＤ
 */
function onCameraStatusNotify(status, cameraId, cameraName, userId) {
    if (userId == room.selfUser.id) {
        if (status == StreamStatus.published) {
            local_video.className = 'openCamera';
        } else if (status == StreamStatus.init) {
            local_video.className = 'closeCamera';
        }
    } else {
        if (status == StreamStatus.published) {
            remote_video.className = 'openCamera';
        } else if (status == StreamStatus.init) {
            remote_video.className = 'closeCamera';
        }
    }
}

//订阅未订阅的视频
function onPublishCameraNotify(videos) {
    videos.forEach(function (video) {
        //只订阅未订阅过的视频
        var subVideoIdsLen = room.selfUser.subVideoIds.length;
        if (subVideoIdsLen > 0) {
            var isSub = false;
            for (var i = 0; i < subVideoIdsLen; i++) {
                var videoId = room.selfUser.subVideoIds[i];
                if (video.id == videoId) {
                    isSub = true;
                    break;
                }
            }
            if (!isSub) {
                video.subscrible();
            }
        } else {
            video.subscrible();
        }
    });
}

/**
 * 订阅远端视频流反馈
 * @param {Object} stream － 远端视频流
 * @param {Object} userId － 所属用户ＩＤ
 * @param {Object} userName－ 所属用户名称
 * @param {Object} cameraId－ 摄像头设备ＩＤ
 */
function onSubscribleCameraResult(stream, userId, userName, cameraId) {
    $('.remoteVideo_userName').html(userName);
    remote_video.className = 'openCamera';
    room.selfUser.attachVideoElementMediaStream(remoteVideo, stream);
}

/**
 * 取消订阅远端视频流反馈
 * @param {Object} userId－ 所属用户ＩＤ
 * @param {Object} userName－所属用户名称
 * @param {Object} cameraId－摄像头设备ＩＤ
 */
function onUnsubscribleCameraResult(userId, userName, cameraId) {
    room.selfUser.attachVideoElementMediaStream(remoteVideo, null);
}

/**
 * 订阅远端音频流反馈
 * @param {Object} stream－ 远端音频流
 * @param {Object} userId－ 所属用户ＩＤ
 * @param {Object} userName－所属用户名称
 */
function onSubscribleMicrophoneResult(stream, userId, userName) {
    remote_audio.className = 'openMicrophone';
    room.selfUser.attachAudioElementMediaStream(remoteAudio, stream);
    
}

/**
 * 取消订阅远端音频流反馈
 * @param {Object} userId－ 所属用户ＩＤ
 * @param {Object} userName－所属用户名称
 */
function onUnsubscribleMicrophoneResult(userId, userName) {
    room.selfUser.attachAudioElementMediaStream(remoteAudio, null);
}


//iPhone手机上，QQ浏览器,搜狗浏览器,火狐浏览器等切换到后台再切回前台，或接听电话后，音视频控件的播放状态会变成暂停，通过监听进行处理。
document.addEventListener("visibilitychange", () => { 
    //当浏览器的某个标签页切换到后台就会触发
	if(document.hidden) {
		console.info("+++visibilitychange页面被挂起");
	//从后台切换到前台时就会触发
	}else {
		console.info("+++visibilitychange页面呼出");
		var videos = document.getElementsByTagName("video");
		for(var video of videos){
		   video.play();
		}
		
		var audios = document.getElementsByTagName("audio");
		for(var audio of audios){
		   audio.play();
		}
    }
});