// Copyright (c) 2023 Tencent. All rights reserved.
// Author: felixyyan

#include "tmg_audio_ctrl_bindings.h"
#include <cstring>
#include "../include/av_error.h"
#include "../include/tmg_sdk.h"
#include "application/ApplicationManager.h"
#include "bindings/sebind/sebind.h"

#define CHECK_AUDIO_CTRL_IS_NULL(ret_val) \
  if (!audio_ctrl_) {                     \
    return ret_val;                       \
  }

TMGAudioCtrlBindings::TMGAudioCtrlBindings(std::shared_ptr<TMGContextBindings> context_bindings) {
  if (!context_bindings) {
    return;
  }
  ITMGContext* current_context = context_bindings->getTmgContext();
  if (current_context) {
    audio_ctrl_ = current_context->GetAudioCtrl();
  }
}

int TMGAudioCtrlBindings::enableMic(bool enable) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->EnableMic(enable);
}

int TMGAudioCtrlBindings::getMicState() {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->GetMicState();
}

int TMGAudioCtrlBindings::enableSpeaker(bool enable) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->EnableSpeaker(enable);
}

int TMGAudioCtrlBindings::getSpeakerState() {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->GetSpeakerState();
}

int TMGAudioCtrlBindings::enableAudioCaptureDevice(bool enable) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->EnableAudioCaptureDevice(enable);
}

bool TMGAudioCtrlBindings::isAudioCaptureDeviceEnabled() {
  CHECK_AUDIO_CTRL_IS_NULL(false);
  return audio_ctrl_->IsAudioCaptureDeviceEnabled();
}

int TMGAudioCtrlBindings::enableAudioPlayDevice(bool enable) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->EnableAudioPlayDevice(enable);
}

bool TMGAudioCtrlBindings::isAudioPlayDeviceEnabled() {
  CHECK_AUDIO_CTRL_IS_NULL(false);
  return audio_ctrl_->IsAudioPlayDeviceEnabled();
}

int TMGAudioCtrlBindings::enableAudioSend(bool enable) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->EnableAudioSend(enable);
}

bool TMGAudioCtrlBindings::isAudioSendEnabled() {
  CHECK_AUDIO_CTRL_IS_NULL(false);
  return audio_ctrl_->IsAudioSendEnabled();
}

int TMGAudioCtrlBindings::enableAudioRecv(bool enable) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->EnableAudioRecv(enable);
}

bool TMGAudioCtrlBindings::isAudioRecvEnabled() {
  CHECK_AUDIO_CTRL_IS_NULL(false);
  return audio_ctrl_->IsAudioRecvEnabled();
}

int TMGAudioCtrlBindings::setMicVolume(int volume) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->SetMicVolume(volume);
}

int TMGAudioCtrlBindings::getMicVolume() {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->GetMicVolume();
}

int TMGAudioCtrlBindings::setSpeakerVolume(int volume) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->SetSpeakerVolume(volume);
}

int TMGAudioCtrlBindings::getSpeakerVolume() {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->GetSpeakerVolume();
}

int TMGAudioCtrlBindings::setSpeakerVolumeByUserID(const std::string& user_id, int volume) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->SetSpeakerVolumeByUserID(user_id.c_str(), volume);
}

int TMGAudioCtrlBindings::getSpeakerVolumeByUserID(const std::string& user_id) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->GetSpeakerVolumeByUserID(user_id.c_str());
}

int TMGAudioCtrlBindings::enableLoopBack(bool enable) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->EnableLoopBack(enable);
}

int TMGAudioCtrlBindings::setAudioRoute(ITMG_AUDIO_ROUTE route) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->SetAudioRoute(route);
}

int TMGAudioCtrlBindings::getMicListCount() {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->GetMicListCount();
}

ccstd::vector<se::Object*> TMGAudioCtrlBindings::getMicList(int n_count) {
  auto se_device_info_list = ccstd::vector<se::Object*>();
  if (n_count <= 0 || !audio_ctrl_) {
    CC_LOG_ERROR("getMicList: Invalid params");
    return se_device_info_list;
  }

  TMGAudioDeviceInfo* device_info_list = new TMGAudioDeviceInfo[n_count];

  int ret = audio_ctrl_->GetMicList(device_info_list, n_count);
  if (ret == nsgme::av::AV_OK) {
    for (int i = 0; i < n_count; i++) {
      auto se_item = se::Object::createPlainObject();
      se_item->setProperty("device_id", se::Value(device_info_list[i].device_id));
      se_item->setProperty("device_name", se::Value(device_info_list[i].device_name));
      se_device_info_list.push_back(se_item);
    }
  }

  delete[] device_info_list;
  return se_device_info_list;
}

int TMGAudioCtrlBindings::selectMic(const std::string& mic_id) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->SelectMic(mic_id.c_str());
}

se::Object* TMGAudioCtrlBindings::getCurrentMic() {
  auto se_device_info = se::Object::createPlainObject();
  if (!audio_ctrl_) {
    return se_device_info;
  }

  TMGAudioDeviceInfo device_info;
  int ret = audio_ctrl_->GetCurrentMic(&device_info);
  if (ret == nsgme::av::AV_OK) {
    se_device_info->setProperty("device_id", se::Value(device_info.device_id));
    se_device_info->setProperty("device_name", se::Value(device_info.device_name));
  }

  return se_device_info;
}

int TMGAudioCtrlBindings::getSpeakerListCount() {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->GetSpeakerListCount();
}

ccstd::vector<se::Object*> TMGAudioCtrlBindings::getSpeakerList(int n_count) {
  auto se_device_info_list = ccstd::vector<se::Object*>();
  if (n_count <= 0 || !audio_ctrl_) {
    CC_LOG_ERROR("getMicList: Invalid params");
    return se_device_info_list;
  }

  TMGAudioDeviceInfo* device_info_list = new TMGAudioDeviceInfo[n_count];

  int ret = audio_ctrl_->GetSpeakerList(device_info_list, n_count);
  if (ret == nsgme::av::AV_OK) {
    for (int i = 0; i < n_count; i++) {
      auto se_item = se::Object::createPlainObject();
      se_item->setProperty("device_id", se::Value(device_info_list[i].device_id));
      se_item->setProperty("device_name", se::Value(device_info_list[i].device_name));
      se_device_info_list.push_back(se_item);
    }
  }

  delete[] device_info_list;
  return se_device_info_list;
}

int TMGAudioCtrlBindings::selectSpeaker(const std::string& speaker_id) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->SelectSpeaker(speaker_id.c_str());
}

se::Object* TMGAudioCtrlBindings::getCurrentSpeaker() {
  auto se_device_info = se::Object::createPlainObject();
  if (!audio_ctrl_) {
    return se_device_info;
  }
  TMGAudioDeviceInfo device_info;
  int ret = audio_ctrl_->GetCurrentSpeaker(&device_info);
  if (ret == nsgme::av::AV_OK) {
    se_device_info->setProperty("device_id", se::Value(device_info.device_id));
    se_device_info->setProperty("device_name", se::Value(device_info.device_name));
  }

  return se_device_info;
}

int TMGAudioCtrlBindings::enableSpatializer(bool enable) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->EnableSpatializer(enable);
}

bool TMGAudioCtrlBindings::isEnableSpatializer() {
  CHECK_AUDIO_CTRL_IS_NULL(false);
  return audio_ctrl_->IsEnableSpatializer();
}

int TMGAudioCtrlBindings::trackingVolume(float interval) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->TrackingVolume(interval);
}

int TMGAudioCtrlBindings::stopTrackingVolume() {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->StopTrackingVolume();
}

int TMGAudioCtrlBindings::getMicLevel() {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->GetMicLevel();
}

int TMGAudioCtrlBindings::getSpeakerLevel() {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->GetSpeakerLevel();
}

int TMGAudioCtrlBindings::getSendStreamLevel() {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->GetSendStreamLevel();
}

int TMGAudioCtrlBindings::getRecvStreamLevel(const std::string& user_id) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->GetRecvStreamLevel(user_id.c_str());
}

int TMGAudioCtrlBindings::addAudioBlackList(const std::string& user_id) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->AddAudioBlackList(user_id.c_str());
}

int TMGAudioCtrlBindings::removeAudioBlackList(const std::string& user_id) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->RemoveAudioBlackList(user_id.c_str());
}

bool TMGAudioCtrlBindings::isUserIDInAudioBlackList(const std::string& user_id) {
  CHECK_AUDIO_CTRL_IS_NULL(false);
  return audio_ctrl_->IsUserIDInAudioBlackList(user_id.c_str());
}

int TMGAudioCtrlBindings::startMicDeviceTest(int interval) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->StartMicDeviceTest(interval);
}

int TMGAudioCtrlBindings::stopMicDeviceTest() {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->StopMicDeviceTest();
}

int TMGAudioCtrlBindings::startSpeakerDeviceTest(const std::string& file_path) {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->StartSpeakerDeviceTest(file_path.c_str());
}

int TMGAudioCtrlBindings::stopSpeakerDeviceTest() {
  CHECK_AUDIO_CTRL_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return audio_ctrl_->StopSpeakerDeviceTest();
}
