#ifndef RT_Room_C_H
#define RT_Room_C_H

#include "common_c.h"
#include "musermanager_c.h"

typedef rtc::RoomMode					AVDRoomMode;
typedef rtc::RoomStatus				AVDRoomStatus;
typedef rtc::ConnectionStatus	AVDConnectionStatus;
typedef rtc::RoomOption				AVDRoomOption;
/**
* 加入房间回调接口
* @param[in] result 加入错误代码。
* @sa join
*/
typedef  void(*AVDFuncRoomJoinResult) (const char* roomId, Result result);

typedef struct _AVDRoomInfo {
	enum RoomMode {
		rm_p2p = 1,
		router = 2,
	};
	char roomId[Max_RoomId];
	char roomName[Max_RoomName];
	char appRoomId[Max_RoomId];
	char roomTopic[Max_RoomName];
	char ownerId[Max_UserId];
	char hostId[Max_UserId];
	char hostPassword[Max_Password];
	char confPassword[Max_Password];
	uint32 startTime;
	uint32 duration;
	uint32 bandwidth;
	uint32 maxAttendee;
	uint32 maxAudio;
	uint32 maxVideo;
	uint32 roomMode;
	AVDRoomStatus status;
	_AVDRoomInfo() :startTime(0), duration(100), bandwidth(1000), maxAttendee(5), maxAudio(3), maxVideo(2), roomMode(0), status(rtc::rs_scheduled) {
		setRoomMode(rtc::rm_mcu);
		memset(roomId, 0, sizeof(roomId));
		memset(roomName, 0, sizeof(roomName));
		memset(appRoomId, 0, sizeof(appRoomId));
		memset(roomTopic, 0, sizeof(roomTopic));
		memset(ownerId, 0, sizeof(ownerId));
		memset(hostId, 0, sizeof(hostId));
		memset(hostPassword, 0, sizeof(hostPassword));
		memset(confPassword, 0, sizeof(confPassword));
	}

public:
	/** 判断是mcu模式房间 */
	AVDBool isMcu() const { return avd_isFlagSet(roomMode, rtc::rm_mcu); }
	/** 设置房间模式
	* @param[in] flag 设置值。
	* @note 每个模式必须单独设置,不能通过 | 操作合并设置。
	*/
	void setRoomMode(AVDRoomMode flag) {
		if (avd_isFlagSet(flag, rtc::clear_set)) {
			uint32 dwFlag = flag;
			avd_clearFlag(dwFlag, rtc::clear_set);
			avd_clearFlag(roomMode, dwFlag);
		}
		else {
			avd_setFlag(roomMode, flag);
		}
	}
}AVDRoomInfo, *LPAVDRoomInfo;
/**
* 房间回调接口类
*
* 房间回调接口定义了房间对象操作的异步返回，房间通知，房间指示。
*/
typedef struct Room_Callback {
	/// 异步返回
	/** 加入房间操作异步返回
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] result 加入错误代码。
	* @sa avd_room_join
	* @sa avd_room_reJoin
	*/
	void(*room_onJoinResult)(AVDHandle roomHandle, Result result);
	/// 指示
	/** 指示用户离开房间
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] reason 离开房间理由代码，正常离开为AVD_OK。
	* @param[in] *fromId 指示发起用户Id。
	*
	* @sa avd_room_kickoutUser
	*/
	void(*room_onLeaveIndication)(AVDHandle roomHandle, Result result, const char* fromId);
	/// 通知
	/** 透明通道，接收到广播数据通知
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] *data 接收到的数据指针。
	* @param[in] len 接收到的数据长度。
	* @param[in] *fromId 发送方用户Id。
	*
	* @sa avd_room_sendPublicData
	*/
	void(*room_onPublicData)(AVDHandle roomHandle, const char* data, uint32 len, const char* fromId);
	/** 透明通道，接收到私有数据通知
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] *data 接收到的数据指针。
	* @param[in] len 接收到的数据长度。
	* @param[in] fromId 发送方用户Id。
	*
	* @sa avd_room_sendPrivateData
	*/
	void(*room_onPrivateData)(AVDHandle roomHandle, const char* data, uint32 len, const char* fromId);
	//
	/** 房间应用层数据更改通知
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] key 应用层数据关键字。
	* @param[in] value 应用层数据关键字相关数据内容。
	*
	* @sa avd_room_updateAppData
	*/
	void(*room_onAppDataNotify)(AVDHandle roomHandle, const char* key, const char* value);
	/** 房间状态通知
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] status 房间状态。
	*/
	void(*room_onRoomStatusNotify)(AVDHandle roomHandle, AVDRoomStatus status);
	/** 房间网络状态通知
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] status 当前网络状态。
	*/
	void(*room_onConnectionStatus)(AVDHandle roomHandle, AVDConnectionStatus status);

	/** 外部设备要求回调通知
	*
	* @param[in] status 当前网络状态。
	*/
	void (*room_onOutgoingInviteStatusNotify)(AVDHandle roomHandle, rtc::OutgoingInviteType type, const char* roomId, const char* addr, rtc::OutgoingStatus status, const char*  msg) ;

	/**
	* 媒体流推送失败通知
	* @param [string] userId -媒体流的用户ID
	* @param [string] userName -媒体流的用户名
	* @param [int] mediaType -媒体流的类型， 1:video; 2:audio; 3:desktop
	* @param [string] deviceId -媒体流的设备ID
	* @param [int] ssrc -媒体流的ssrc
	*/
	void(*room_onStreamKeepAliveTimeoutNotify)(AVDHandle roomHandle, const char* userId, const char* userName, int mediaType, const char* deviceId, int ssrc);
	Room_Callback() {
		room_onJoinResult = NULL;
		room_onLeaveIndication = NULL;
		room_onPublicData = NULL;
		room_onPrivateData = NULL;
		room_onAppDataNotify = NULL;
		room_onRoomStatusNotify = NULL;
		room_onConnectionStatus = NULL;
		room_onOutgoingInviteStatusNotify = NULL;
		room_onStreamKeepAliveTimeoutNotify = NULL;
	}
}*LPRoom_Callback;

///
/**
* 房间接口类
*
* 房间接口定义了房间对象创建和释放、房间功能操作。
*/
extern "C" {
	/** 初始化房间管理接口
	*
	* @param[in] *roomId 房间ID。
	* @param[in] cb 房间回调接口指针。
	* @param[out] roomHandle 房间句柄。
	* @return 返回错误代码。
	* @sa Room_Callback
	*/
	RT_API_EXPORT Result avd_room_init(const char* roomId, LPRoom_Callback cb, AVDHandle& roomHandle);
	/** 同上，
	* @param[in] *userId 用户ID。
	* @param[in] *roomId 房间ID。
	* @param[in] cb 房间回调接口指针。
	* @param[out] roomHandle 房间句柄。
	*/
	RT_API_EXPORT Result avd_room_initWithUserId(const char* roomId, const char* userId, LPRoom_Callback cb, AVDHandle& roomHandle);
	/** 反初始化房间管理接口
	*
	* @param[in] roomHandle 房间句柄。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_uninit(AVDHandle roomHandle);
	/** 当前用户加入房间
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in,out] user 用户信息：用户Id，用户名，用户数据等；当应用层不传入user.userId时，SDK将创建一个新的guid作为user.userId，同时返回给应用层。
	* @param[in] password 密码：如果是主持人请用主持人密码；如果是其他参会者，请用房间密码。
	* @param[in] joinresult 加房间回调接口。
	* @note 加入房间时，可以指定结果单独回调接口；如果指定，则在指定单独接口回调，不会在Listener的onJoinResult回调。
	* @return 返回错误代码。
	* @sa AVDUser
	*/
	RT_API_EXPORT Result avd_room_join(AVDHandle roomHandle, const AVDUser& user, const char* password, AVDFuncRoomJoinResult joinresult);

	RT_API_EXPORT AVDBool avd_room_isWorking(AVDHandle roomHandle);

	/** 当前用户加入房间
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in,out] user 用户信息：用户Id(不能包含'{'、'}'字符)，用户名，用户数据等；当应用层不传入user.userId时，SDK将创建一个新的guid作为user.userId，同时返回给应用层。
	* @param[in] password 密码：如果是主持人请用主持人密码；如果是其他参会者，请用房间密码。
	* @param[in] joinresult 加房间回调接口。
	* @param[in] roomToken 房间token。
	* @note 加入房间时，可以指定结果单独回调接口；如果指定，则在指定单独接口回调，不会在Listener的onJoinResult回调。
	* @return 返回错误代码。
	* @sa AVDUser
	*/
	RT_API_EXPORT Result avd_room_joinWithToken(AVDHandle roomHandle, const AVDUser& user, const char* password, AVDFuncRoomJoinResult joinresult, const char* roomToken);

	/** 当前用户离开房间
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] reason 用户离开房间的原因代码，正常离开为AVD_OK。
	*
	* @note 当前用户离开房间后，当前房间对象和房间的各功能模块都处于离会状态，功能操作无效。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_leave(AVDHandle roomHandle, Result reason);

	/** 关闭房间
	* @note 关闭房间，房间中所有人将被踢出房间，接收到 onLeaveIndication, reason是 Err_Room_closed
	* @sa onLeaveIndication
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_close(AVDHandle roomHandle);

	/** 重新加入当前房间
	*
	* @param[in] roomHandle 房间句柄。
	* @note 当用户主动离开房间或者中间网络断线后离开房间后，可以重新调用此函数加入房间。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_reJoin(AVDHandle roomHandle);
	/** 重置房间中网络连接
	*
	* @note 当上层检测到网络切换等情况下，可以调用此接口进行网络连接重置。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_reConnect(AVDHandle roomHandle);
	/** 房间中踢出用户
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] reason 踢出用户的理由代码。
	* @param[in] *userId 被踢出用户Id。
	*
	* @note 被踢用户将会在room_onLeaveIndication中接收到回调，被踢用户直接调用 leave 离开房间即可。
	* @return 返回错误代码。
	* @sa room_onLeaveIndication
	*/
	RT_API_EXPORT Result avd_room_kickoutUser(AVDHandle roomHandle, Result reason, const char* userId);

	/** 更新房间状态
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] status 房间状态。
	*
	* @return 返回错误代码。
	* @sa AVDRoomStatus
	*/
	RT_API_EXPORT Result avd_room_updateRoomStatus(AVDHandle roomHandle, AVDRoomStatus status);

	/** 获取房间状态
	*
	* @param[in] roomHandle 房间句柄。
	* @return 返回房间状态。
	* @sa AVDRoomStatus
	*/
	RT_API_EXPORT AVDRoomStatus avd_room_getRoomStatus(AVDHandle roomHandle);

	/** 返回应用层的房间数据
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] key 房间数据关键字。
	* @param[in] value 相应关键字的房间数据。
	* @param[in] size 房间数据长度。
	*
	* @note 应用层的房间数据方便应用层在房间中保留关于房间的一些业务逻辑数据，可以获取和修改应用层的房间数据。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_getAppData(AVDHandle roomHandle, const char* key, char* value, uint32& size);
	/** 修改应用层的房间数据
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] key 房间数据关键字。
	* @param[in] value 房间数据对应关键字的信息内容
	*
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_updateAppData(AVDHandle roomHandle, const char* key, const char* value);
	
	//
	/** 获取房间Id
	*
	* @param[in] roomHandle 房间句柄。
	* @param[out] roomId 房间ID。
	* @param[in,out] dwsize 请求长度，实际房间ID长度。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_getRoomId(AVDHandle roomHandle, char* roomId, uint32& dwsize);
	/** 获取房间应用层Id
	*
	* @param[in] roomHandle 房间句柄。
	* @param[out] appRoomId 房间应用层ID。
	* @param[in,out] dwsize 请求长度，房间应用层ID长度。
	* @return 返回错误代码。
	* @note 房间应用层Id在应用层安排当前房间的时候由应用层来指定，方便应用层查找、标示房间。
	*/
	RT_API_EXPORT Result avd_room_getAppRoomId(AVDHandle roomHandle, char* appRoomId, uint32& dwsize);
	/** 获取房间名
	*
	* @param[in] roomHandle 房间句柄。
	* @param[out] roomName 房间名称。
	* @param[in,out] dwsize 请求长度，房间名称长度。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_getRoomName(AVDHandle roomHandle, char* roomName, uint32& dwsize);

	/** 获取房间主题
	*
	* @param[in] roomHandle 房间句柄。
	* @param[out] roomTopic 房间主题。
	* @param[in,out] dwsize 请求长度，房间主题长度。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_getRoomTopic(AVDHandle roomHandle, char* roomTopic, uint32& dwsize);

	/** 获取房间信息
	*
	* @param[in] roomHandle 房间句柄。
	* @param[out] info 房间信息。
	* @return 返回错误代码。
	* @sa AVDRoomInfo
	*/
	RT_API_EXPORT Result avd_room_getRoomInfo(AVDHandle roomHandle, AVDRoomInfo& info);
	//
	/** 透明通道，发送广播数据
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] *data 发送的数据指针。
	* @param[in] len 发送的数据长度。
	*
	* @note 此透明通道用于承载应用层数据，广播给所有房间内用户。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_sendPublicData(AVDHandle roomHandle, const char* data, uint32 len);

	/** 透明通道，发送私有数据
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] *data 发送的数据指针。
	* @param[in] len 发送的数据长度。
	* @param[in] *toId 目的用户Id。
	*
	* @note 此透明通道用于承载应用层数据，发送给房间内某一特定用户。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_sendPrivateData(AVDHandle roomHandle, const char* data, uint32 len, const char* toId);
	/** 当前房间启用或关闭流量统计功能
	* @param[in] roomHandle 房间句柄。
	* @param[in] isEnable 启用或关闭。
	* @return 返回错误代码：
	* 	AVD_OK						成功
	*/
	RT_API_EXPORT Result avd_room_enableStats(AVDHandle roomHandle, AVDBool isEnable);
	/** 获取房间的流量统计信息
	* @param[in] roomHandle 房间句柄。
	* @param[in] stats      房间统计信息。
	* @return 返回房间流量统计信息。
	* @sa RoomStats
	*/
	RT_API_EXPORT Result avd_room_getRoomStats(AVDHandle roomHandle, AVDRoomStats& stats);
	/** 获取某路媒体（音频或者视频）的流量统计信息
	* @param[in] roomHandle 房间句柄。
	* @param[in] deviceId 设备Id。
	* @param[in] stats    媒体统计信息。
	* @return 返回媒体统计信息。
	* @sa MediaStats
	*/
	RT_API_EXPORT Result avd_room_getMediaStats(AVDHandle roomHandle, const char* deviceId, AVDMediaStats& stats);
	RT_API_EXPORT Result avd_room_getAudioStats(AVDHandle roomHandle, AVDMediaStats& stats);

	//
	/** 设置房间选项
	* @param[in] roomHandle 房间句柄。
	* @param[in] type 房间选项类型。
	* @param[in] value 房间选项值指针。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_setOption(AVDHandle roomHandle, AVDRoomOption type, void* value);
	RT_API_EXPORT Result avd_room_setOption2(AVDHandle roomHandle, AVDRoomOption type, const char* value);
	/** 获取房间选项
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] type 房间选项类型。
	* @param[out] value 房间选项返回值指针。
	*
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_room_getOption(AVDHandle roomHandle, AVDRoomOption type, void* value);
	RT_API_EXPORT Result avd_room_getOption2(AVDHandle roomHandle, AVDRoomOption type, char* value, uint32& size);
}
#endif//RT_Room_C_H
