#include "use_audio.h"
#include "api_c/avdengine_c.h"
#include "listenerset.h"
#include "log2ui.h"
#include "transfer_c_cpp.h"

static ListenerSet<Use_Audio> sets;
///
Use_Audio::Use_Audio(QWidget *parent) : Com_Audio(parent), room_(0), module_(0), moduledevice_(0) {
}
Use_Audio::~Use_Audio() {
}
void Use_Audio::onAttach(AVDHandle room) {
	if (0 == room) {
		module_ = 0;
	}
	else {
		cb_module_.audio_onMicrophoneStatusNotify = Use_Audio::s_onMicrophoneStatusNotify;
		cb_module_.audio_onAudioLevelMonitorNotify = Use_Audio::s_onAudioLevelMonitorNotify;
		cb_module_.audio_onOpenMicrophoneResult = Use_Audio::s_onOpenMicrophoneResult;
		cb_module_.audio_onCloseMicrophoneResult = Use_Audio::s_onCloseMicrophoneResult;
		avd_audio_init(room, &cb_module_, module_);
		avd_audiodevice_init(module_, &cb_moduledevice_, moduledevice_);
		room_ = room;
		sets.add(this);
	}
	Com_Audio::onAttach();
}
void Use_Audio::onDetach() {
	sets.remove(module_);
	if (moduledevice_) {
		avd_audiodevice_uninit(moduledevice_);
		moduledevice_ = 0;
	}
	if (module_) {
		avd_audio_uninit(module_);
		module_ = 0;
	}
	room_ = 0;
	Com_Audio::onDetach();
}
void Use_Audio::updateLocalMicrophones() {
	if (!isAttach()) {
		return;
	}
	Com_Audio::updateLocalMicrophones();
	uint32_t ncount = avd_audiodevice_getMicrophoneCount(moduledevice_);
	AVDMicrophone* pitems = new AVDMicrophone[ncount];
	avd_audiodevice_getMicrophones(moduledevice_, ncount, pitems);
	for (uint32_t i = 0; i < ncount; ++i) {
		QListWidgetAddItem(ui.lst_audio_localMicrophones, pitems[i].name, pitems[i].id);
	}
	delete[] pitems;
}
void Use_Audio::updateLocalSpeakers() {
	if (!isAttach()) {
		return;
	}
	Com_Audio::updateLocalSpeakers();
	uint32_t ncount = avd_audiodevice_getSpeakerCount(moduledevice_);
	AVDSpeaker* pitems = new AVDSpeaker[ncount];
	avd_audiodevice_getSpeakers(moduledevice_, ncount, pitems);
	for (uint32_t i = 0; i < ncount; ++i) {
        QListWidgetAddItem(ui.lst_audio_localSpeakers, pitems[i].name, pitems[i].id);
	}
	delete[] pitems;
}

///
bool Use_Audio::api_engineSetOption(rtc::EngineOption option, void* value) {
	avd_engine_setOption(option, value);
	return true;
}
bool Use_Audio::api_roomSetOption(rtc::RoomOption option, std::string& value) {
	avd_room_setOption2(room_, option, value.c_str());
	return true;
}
Result Use_Audio::api_openMicrophone(bool open) {
	return open ? avd_audio_openMicrophone(module_) : avd_audio_closeMicrophone(module_);
}
Result Use_Audio::api_muteMicrophone(bool mute) {
	return mute ? avd_audio_muteMicrophone(module_) : avd_audio_unmuteMicrophone(module_);
}
Result Use_Audio::api_muteSpeaker(bool mute) {
	return mute ? avd_audio_muteSpeaker(module_) : avd_audio_unmuteSpeaker(module_);
}
Result Use_Audio::api_monitorAudioLevel(bool enable) {
	return enable ? avd_audio_monitorAudioLevel(module_) : avd_audio_unmonitorAudioLevel(module_);
}
Result Use_Audio::api_setRecordingMicrophone(const rtc::DeviceId& curId) {
	return avd_audiodevice_setRecordingMicrophone(moduledevice_, curId.c_str());
}
Result Use_Audio::api_setPlayoutSpeaker(const rtc::DeviceId& curId) {
	return avd_audiodevice_setPlayoutSpeaker(moduledevice_, curId.c_str());
}
Result Use_Audio::api_applyPlayoutGain(float gain) {
	return avd_engine_setOption(rtc::eo_audio_agc_PlayoutGainMultipleValue, &gain);
}

///
void Use_Audio::s_onMicrophoneStatusNotify(AVDHandle handle, AVDMicrophoneStatus status, const char* fromUserId) {
	Use_Audio* item = sets.getItem(handle);
	if (item) { item->onMicrophoneStatusNotify(status, fromUserId); }
}
void Use_Audio::s_onAudioLevelMonitorNotify(AVDHandle handle, const AVDAudioInfo& citem) {
	Use_Audio* item = sets.getItem(handle);
	if (item) { 
		rtc::AudioInfo cppitem;
		utility::AudioInfoC2Cpp(citem, cppitem);
		item->onAudioLevelMonitorNotify(cppitem);
	}
}
void Use_Audio::s_onOpenMicrophoneResult(AVDHandle handle, Result result) {
	Use_Audio* item = sets.getItem(handle);
	if (item) { item->onOpenMicrophoneResult(result); }
}
void Use_Audio::s_onCloseMicrophoneResult(AVDHandle handle, Result result) {
	Use_Audio* item = sets.getItem(handle);
	if (item) { item->onCloseMicrophoneResult(result); }
}
