#include "use_video.h"
#include "api_c/avdengine_c.h"
#include "api_c/musermanager_c.h"
#include "transfer_c_cpp.h"
#include "log2ui.h"
#include <QtGui/QVector3D>
#include "listenerset.h"
#include "videoview.h"

static ListenerSet<Use_Video> sets;
///
Use_Video::Use_Video(QWidget *parent) : Com_Video(parent), room_(0), usermanager_(0), module_(0), moduledevice_(0) {
}
Use_Video::~Use_Video() {
}
void Use_Video::onAttach(AVDHandle room) {
	if (0 == room) {
		module_ = 0;
	}
	else {
		cb_module_.video_onCameraStatusNotify = Use_Video::s_onCameraStatusNotify;
		cb_module_.video_onCameraDataNotify = Use_Video::s_onCameraDataNotify;
		cb_module_.video_onPublishCameraNotify = Use_Video::s_onPublishCameraNotify;
		cb_module_.video_onUnpublishCameraNotify = Use_Video::s_onUnpublishCameraNotify;
		cb_module_.video_onSubscribeResult = Use_Video::s_onSubscribeResult;
		cb_module_.video_onUnsubscribeResult = Use_Video::s_onUnsubscribeResult;
		cb_module_.video_onPublishLocalResult = Use_Video::s_onPublishLocalResult;
		cb_module_.video_onUnpublishLocalResult = Use_Video::s_onUnpublishLocalResult;
		avd_video_init(room, &cb_module_, module_);
		avd_videodevice_init(module_, &cb_moduledevice_, moduledevice_);
		room_ = room;
		usermanager_ = avd_usermanager_gethandle(room);
		sets.add(this);
	}
	Com_Video::onAttach();
}
void Use_Video::onDetach() {
	sets.remove(module_);
	if (moduledevice_) {
		avd_videodevice_uninit(moduledevice_);
		moduledevice_ = 0;
	}
	if (module_) {
		avd_video_uninit(module_);
		module_ = 0;
	}
	usermanager_ = 0;
	room_ = 0;
	Com_Video::onDetach();
}
void Use_Video::updateLocalCameras() {
	if (!isAttach()) {
		return;
	}
	Com_Video::updateLocalCameras();
	uint32_t ncount = avd_videodevice_getLocalCameraCount(moduledevice_);
	AVDCamera* pitems = new AVDCamera[ncount];
	avd_videodevice_getLocalCameras(moduledevice_, ncount, pitems);
	for (uint32_t i = 0; i < ncount; ++i) {
		QListWidgetAddItem(ui.lst_video_localCameras, pitems[i].videodevice.device.name, pitems[i].videodevice.device.id);
	}
	delete[] pitems;
}
void Use_Video::updateRemotePublishedCameras() {
	if (!isAttach()) {
		return;
	}
	Com_Video::updateRemotePublishedCameras();
	uint32_t ncount = avd_video_getPublishedCameraCount(module_);
	AVDCamera* pitems = new AVDCamera[ncount];
	avd_video_getPublishedCameras(module_, ncount, pitems);
	for (uint32_t i = 0; i < ncount; ++i) {
		QListWidgetAddItem(ui.lst_video_remotePublishedCameras, pitems[i].videodevice.device.name, pitems[i].videodevice.device.id);
	}
	delete[] pitems;
}
void Use_Video::fillResolutions() {
	if (!isAttach()) {
		return;
	}
	Com_Video::fillResolutions();
	rtc::DeviceId selId = getSelectedDeviceId(ui.lst_video_localCameras);
	if (selId.empty()) {
		return;
	}
	uint32_t ncount = avd_videodevice_getCameraCapabilitiesCount(moduledevice_, selId.c_str());
	AVDCameraCapability* pitems = new AVDCameraCapability[ncount];
	avd_videodevice_getCameraCapabilities(moduledevice_, selId.c_str(), ncount, pitems);
	for (uint32_t i = 0; i < ncount; ++i) {
		QString sitem;
		sitem.sprintf("%dx%d %d", pitems[i].width, pitems[i].height, pitems[i].maxFPS);
		QVector3D qtdata(pitems[i].width, pitems[i].height, pitems[i].maxFPS);
		ui.cbo_video_resolutions->addItem(sitem, qtdata);
	}
	delete [] pitems;
}
///
bool Use_Video::api_engineSetOption(rtc::EngineOption option, void* value) {
	avd_engine_setOption(option, value);
	return true;
}
bool Use_Video::api_isSelfDevice(const rtc::DeviceId& dId) const {
	return isAttach() ? avd_usermanager_isSelfDevice(usermanager_, dId.c_str()) : false;
}
Result Use_Video::api_attachRender(const rtc::DeviceId& dId, IVideoView* view) {
	return avd_video_attachRender(module_, dId.c_str(), view->getRender());
}
Result Use_Video::api_detachRender(const rtc::DeviceId& dId) {
	return avd_video_detachRenderWithDeviceId(module_, dId.c_str());
}
Result Use_Video::api_detachRender_1(IVideoView* view) {
	return avd_video_detachRender(module_, view->getRender());
}
Result Use_Video::api_subscribe(const rtc::DeviceId& dId) {
	return avd_video_subscribe(module_, dId.c_str());
}
Result Use_Video::api_unsubscribe(const rtc::DeviceId& dId) {
	return avd_video_unsubscribe(module_, dId.c_str());
}
Result Use_Video::api_muteLocalCamera(const rtc::DeviceId& dId) {
	return avd_video_muteLocalCamera(module_, dId.c_str());
}
Result Use_Video::api_unmuteLocalCamera(const rtc::DeviceId& dId) {
	return avd_video_unmuteLocalCamera(module_, dId.c_str());
}
Result Use_Video::api_publishLocalCamera(const rtc::Camera& cam) {
	AVDCamera ccam;
	utility::CameraCpp2C(cam, ccam);
	return avd_video_publishLocalCameraWithDevice(module_, ccam);
}
Result Use_Video::api_unpublishLocalCamera() {
	return avd_video_unpublishLocalCamera(module_);
}
Result Use_Video::api_previewLocalCamera(const rtc::DeviceId& dId) {
	return avd_video_previewLocalCameraWithDeviceId(module_, dId.c_str(),localview_->getRender());
}
Result Use_Video::api_unpreviewLocalCamera() {
	return avd_video_unpreviewLocalCamera(module_);
}
Result Use_Video::api_setVideoBitrate(const rtc::DeviceId& dId, int min, int max) {
	return avd_video_setVideoBitrate(module_, dId.c_str(), min, max);
}
Result Use_Video::api_changeCapability(const rtc::DeviceId& dId, const rtc::CameraCapability& cap) {
	AVDCameraCapability ccap(cap.width, cap.height, cap.maxFPS);
	return avd_video_updateCaptureCapability(module_, dId.c_str(), ccap);
}
void Use_Video::api_switchIndexvideo(int index) {
}
///
#define qDebug_Mod qDebug() << Utf8Str("---- Video ")
const rtc::MediaStats& Use_Video::getMediaStats() {
	if (!isAttach() || curLocalId_.empty()) {
        return g_emptyMediaStats;
    }

	AVDRoomStats rstats;
	avd_room_getRoomStats(room_, rstats);
	qDebug_Mod << Utf8Str(" ") << QDateTime::currentDateTime().toString("hh:mm:ss")
		<< Utf8Str(" room 速率-s ") << rstats.netstats.bps_sent << Utf8Str(" -r ") << rstats.netstats.bps_received
		<< Utf8Str(",丢包-") << rstats.netstats.lostpercent;
	AVDMediaStats astats;
	avd_room_getAudioStats(room_, astats);
	qDebug_Mod << Utf8Str(" ") << QDateTime::currentDateTime().toString("hh:mm:ss")
		<< Utf8Str(" audio 速率-s ") << astats.netstats.bps_sent << Utf8Str(" -r ") << astats.netstats.bps_received
		<< Utf8Str(",丢包-") << astats.netstats.lostpercent;

	AVDMediaStats stats;
    avd_room_getMediaStats(room_, curLocalId_.c_str(), stats);
	qDebug_Mod << Utf8Str(" ") << QDateTime::currentDateTime().toString("hh:mm:ss")
		<< Utf8Str(" local video 速率-s ") << stats.netstats.bps_sent << Utf8Str(" -r ") << stats.netstats.bps_received
		<< Utf8Str(",丢包-") << stats.netstats.lostpercent;

	AVDMediaStats aaastats;
	avd_room_getMediaStats(room_, curRemoteId_.c_str(), aaastats);
	qDebug_Mod << Utf8Str(" ") << QDateTime::currentDateTime().toString("hh:mm:ss")
		<< Utf8Str(" remote video 速率-s ") << aaastats.netstats.bps_sent << Utf8Str(" -r ") << aaastats.netstats.bps_received
		<< Utf8Str(",丢包-") << aaastats.netstats.lostpercent;

    utility::MediaStatsC2Cpp(stats, mediastats_);
    return mediastats_;
}
rtc::Camera Use_Video::api_getCamera(const rtc::DeviceId& dId) {
	AVDCamera item;
	avd_videodevice_getCamera(moduledevice_, dId.c_str(), item);
	rtc::Camera cppitem;
	utility::CameraC2Cpp(item, cppitem);
	return cppitem;
}
///
void Use_Video::s_onCameraStatusNotify(AVDHandle handle, AVDCameraStatus status, const char* fromId) {
	Use_Video* item = sets.getItem(handle);
	if (item) { item->onCameraStatusNotify(status, fromId); }
}
void Use_Video::s_onCameraDataNotify(AVDHandle handle, int level, const char* description, const char* fromId) {
	Use_Video* item = sets.getItem(handle);
	if (item) { item->onCameraDataNotify(level, description, fromId); }
}
void Use_Video::s_onPublishCameraNotify(AVDHandle handle, const AVDCamera& camera) {
	Use_Video* item = sets.getItem(handle);
	if (item) { 
		rtc::Camera cppcamera;
		utility::CameraC2Cpp(camera, cppcamera);
		item->onPublishCameraNotify(cppcamera);
	}
}
void Use_Video::s_onUnpublishCameraNotify(AVDHandle handle, const AVDCamera& camera) {
	Use_Video* item = sets.getItem(handle);
	if (item) { 
		rtc::Camera cppcamera;
		utility::CameraC2Cpp(camera, cppcamera);
		item->onUnpublishCameraNotify(cppcamera);
	}
}
void Use_Video::s_onSubscribeResult(AVDHandle handle, Result result, const char* fromId) {
	Use_Video* item = sets.getItem(handle);
	if (item) { item->onSubscribeResult(result, fromId); }
}
void Use_Video::s_onUnsubscribeResult(AVDHandle handle, Result result, const char* fromId) {
	Use_Video* item = sets.getItem(handle);
	if (item) { item->onUnsubscribeResult(result, fromId); }
}
void Use_Video::s_onPublishLocalResult(AVDHandle handle, Result result, const char* fromId) {
	Use_Video* item = sets.getItem(handle);
	if (item) { item->onPublishLocalResult(result, fromId); }
}
void Use_Video::s_onUnpublishLocalResult(AVDHandle handle, Result result, const char* fromId) {
	Use_Video* item = sets.getItem(handle);
	if (item) { item->onUnpublishLocalResult(result, fromId); }
}
