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

#include "tmg_room_bindings.h"
#include "../include/av_error.h"
#include "../include/av_room.h"
#include "../include/av_type.h"

namespace {
#define CHECK_ROOM_IS_NULL(ret_val) \
  if (!room_) {                     \
    return ret_val;                 \
  }
const int kPositionArryLen = 3;
}  // namespace

TMGRoomBindings::TMGRoomBindings(std::shared_ptr<TMGContextBindings> context_bindings) {
  if (!context_bindings) {
    return;
  }
  ITMGContext* current_context = context_bindings->getTmgContext();
  if (current_context) {
    room_ = current_context->GetRoom();
  }
}

std::string TMGRoomBindings::getRoomID() {
  CHECK_ROOM_IS_NULL("");
  return room_->GetRoomID();
}

int TMGRoomBindings::changeRoomType(ITMG_ROOM_TYPE room_type) {
  CHECK_ROOM_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return room_->ChangeRoomType(room_type);
}

int TMGRoomBindings::getRoomType() {
  CHECK_ROOM_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return room_->GetRoomType();
}

int TMGRoomBindings::startRoomSharing(const std::string& target_room_id,
                                      const std::string& target_user_id,
                                      const std::string& user_sig,
                                      int user_sig_len) {
  CHECK_ROOM_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return room_->StartRoomSharing(target_room_id.c_str(), target_user_id.c_str(), user_sig.c_str(),
                                 user_sig_len);
}

int TMGRoomBindings::stopRoomSharing() {
  CHECK_ROOM_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return room_->StopRoomSharing();
}

int TMGRoomBindings::switchRoom(const std::string& target_room_id, const std::string& user_sig) {
  CHECK_ROOM_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return room_->SwitchRoom(target_room_id.c_str(), user_sig.c_str(), user_sig.length());
}

int TMGRoomBindings::sendCustomData(unsigned char* data, int length, int repeat_count) {
  CHECK_ROOM_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  if (data == nullptr) {
    return nsgme::av::AV_ERR_INVALID_ARGUMENT;
  }
  std::string str(reinterpret_cast<char*>(data), length);
  return room_->SendCustomData(str.c_str(), str.length(), repeat_count);
}

int TMGRoomBindings::stopSendCustomData() {
  CHECK_ROOM_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return room_->StopSendCustomData();
}

int TMGRoomBindings::updateAudioRecvRange(float range) {
  CHECK_ROOM_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return room_->UpdateAudioRecvRange(range);
}

int TMGRoomBindings::updateSpatializerRecvRange(float range) {
  CHECK_ROOM_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  return room_->UpdateSpatializerRecvRange(range);
}

int TMGRoomBindings::updateSelfPosition(const float* position,
                                        const int position_len,
                                        const float* axis_forward,
                                        const int axis_forward_len,
                                        const float* axis_right,
                                        const int axis_right_len,
                                        const float* axis_up,
                                        const int axis_up_len) {
  CHECK_ROOM_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  if (position_len != kPositionArryLen || position == nullptr ||
      axis_forward_len != kPositionArryLen || axis_forward == nullptr ||
      axis_right_len != kPositionArryLen || axis_right == nullptr ||
      axis_up_len != kPositionArryLen || axis_up == nullptr) {
    return nsgme::av::AV_ERR_INVALID_ARGUMENT;
  }
  float current_position[kPositionArryLen];
  float current_axis_forward[kPositionArryLen];
  float current_axis_right[kPositionArryLen];
  float current_axis_up[kPositionArryLen];
  for (int i = 0; i < position_len; i++) {
    current_position[i] = position[i];
    current_axis_forward[i] = axis_forward[i];
    current_axis_right[i] = axis_right[i];
    current_axis_up[i] = axis_up[i];
  }

  return room_->UpdateSelfPosition(current_position, current_axis_forward, current_axis_right,
                                   current_axis_up);
}

int TMGRoomBindings::updateOtherPosition(const std::string& user_id,
                                         const float* position,
                                         int position_len) {
  CHECK_ROOM_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  if (position_len != kPositionArryLen && position == nullptr) {
    return nsgme::av::AV_ERR_INVALID_ARGUMENT;
  }
  float current_position[kPositionArryLen];
  for (int i = 0; i < position_len; i++) {
    current_position[i] = position[i];
  }
  return room_->UpdateOtherPosition(user_id.c_str(), current_position);
}

int TMGRoomBindings::sendSEIMsg(unsigned char* message, int length, int repeat_count) {
  CHECK_ROOM_IS_NULL(nsgme::av::AV_ERR_UNKNOWN);
  if (message == nullptr) {
    return nsgme::av::AV_ERR_INVALID_ARGUMENT;
  }
  std::string str(reinterpret_cast<char*>(message), length);
  return room_->SendSEIMsg(str.c_str(), repeat_count);
}
