import 'dart:ffi'; // 引入 FFI 库
import 'package:ffi/ffi.dart'; // 导入 ffi 扩展方法
import 'tmg_load_dynamic.dart';

typedef EnableAudioCaptureDeviceNative =
    Int32 Function(Pointer<Void>, Int8 enable);
typedef EnableAudioCaptureDeviceDart = int Function(Pointer<Void>, int enable);

typedef IsAudioCaptureDeviceEnabledNative = Int8 Function(Pointer<Void>);
typedef IsAudioCaptureDeviceEnabledDart = int Function(Pointer<Void>);

typedef EnableAudioPlayDeviceNative =
    Int32 Function(Pointer<Void>, Int8 enable);
typedef EnableAudioPlayDeviceDart = int Function(Pointer<Void>, int enable);

typedef IsAudioPlayDeviceEnabledNative = Int8 Function(Pointer<Void>);
typedef IsAudioPlayDeviceEnabledDart = int Function(Pointer<Void>);

typedef EnableAudioSendNative = Int32 Function(Pointer<Void>, Int8 enable);
typedef EnableAudioSendDart = int Function(Pointer<Void>, int enable);

typedef IsAudioSendEnabledNative = Int8 Function(Pointer<Void>);
typedef IsAudioSendEnabledDart = int Function(Pointer<Void>);

typedef EnableAudioRecvNative = Int32 Function(Pointer<Void>, Int8 enable);
typedef EnableAudioRecvDart = int Function(Pointer<Void>, int enable);

typedef IsAudioRecvEnabledNative = Int8 Function(Pointer<Void>);
typedef IsAudioRecvEnabledDart = int Function(Pointer<Void>);

typedef SetMicVolumeNative = Int32 Function(Pointer<Void>, Int32 volume);
typedef SetMicVolumeDart = int Function(Pointer<Void>, int volume);

typedef GetMicVolumeNative = Int32 Function(Pointer<Void>);
typedef GetMicVolumeDart = int Function(Pointer<Void>);

typedef SetSpeakerVolumeNative = Int32 Function(Pointer<Void>, Int32 volume);
typedef SetSpeakerVolumeDart = int Function(Pointer<Void>, int volume);

typedef GetSpeakerVolumeNative = Int32 Function(Pointer<Void>);
typedef GetSpeakerVolumeDart = int Function(Pointer<Void>);

typedef SetSpeakerVolumeByUserIDNative =
    Int32 Function(Pointer<Void>, Pointer<Int8> userID, Int32 volume);
typedef SetSpeakerVolumeByUserIDDart =
    int Function(Pointer<Void>, Pointer<Int8> userID, int volume);

typedef GetSpeakerVolumeByUserIDNative =
    Int32 Function(Pointer<Void>, Pointer<Int8> userID);
typedef GetSpeakerVolumeByUserIDDart =
    int Function(Pointer<Void>, Pointer<Int8> userID);

typedef EnableLoopBackNative = Int32 Function(Pointer<Void>, Int8 enable);
typedef EnableLoopBackDart = int Function(Pointer<Void>, int enable);

typedef SetLoopBackVolumeNative = Int32 Function(Pointer<Void>, Int32 volume);
typedef SetLoopBackVolumeDart = int Function(Pointer<Void>, int volume);

typedef AddAudioBlackListNative =
    Int32 Function(Pointer<Void>, Pointer<Int8> userID);
typedef AddAudioBlackListDart =
    int Function(Pointer<Void>, Pointer<Int8> userID);

typedef RemoveAudioBlackListNative =
    Int32 Function(Pointer<Void>, Pointer<Int8> userID);
typedef RemoveAudioBlackListDart =
    int Function(Pointer<Void>, Pointer<Int8> userID);

typedef IsUserIDInAudioBlackListNative =
    Int8 Function(Pointer<Void>, Pointer<Int8> userID);
typedef IsUserIDInAudioBlackListDart =
    int Function(Pointer<Void>, Pointer<Int8> userID);

typedef EnableSpatializerNative = Int32 Function(Pointer<Void>, Int8 enable);
typedef EnableSpatializerDart = int Function(Pointer<Void>, int enable);

typedef IsEnableSpatializerNative = Int8 Function(Pointer<Void>);
typedef IsEnableSpatializerDart = int Function(Pointer<Void>);

typedef TrackingVolumeNative = Int32 Function(Pointer<Void>, Float interval);
typedef TrackingVolumeDart = int Function(Pointer<Void>, double interval);

typedef StopTrackingVolumeNative = Int32 Function(Pointer<Void>);
typedef StopTrackingVolumeDart = int Function(Pointer<Void>);

typedef GetMicLevelNative = Int32 Function(Pointer<Void>);
typedef GetMicLevelDart = int Function(Pointer<Void>);

typedef GetSpeakerLevelNative = Int32 Function(Pointer<Void>);
typedef GetSpeakerLevelDart = int Function(Pointer<Void>);

typedef GetSendStreamLevelNative = Int32 Function(Pointer<Void>);
typedef GetSendStreamLevelDart = int Function(Pointer<Void>);

typedef GetRecvStreamLevelNative =
    Int32 Function(Pointer<Void>, Pointer<Int8> userID);
typedef GetRecvStreamLevelDart =
    int Function(Pointer<Void>, Pointer<Int8> userID);

class TMGAudioCtrlBindings {
  late final Pointer<Void> _gmeInstance;
  TMGLoadDynamic _tmgDynamicInstance = TMGLoadDynamic.GetInstance();
  DynamicLibrary? _gmeSdkLib = null;

  TMGAudioCtrlBindings() {
    _gmeSdkLib = _tmgDynamicInstance.GetGmeSdkLib();
    _gmeInstance = _tmgDynamicInstance.GetGmeSdkInstance();
  }

  int EnableMic(bool enable) {
    int ret1 = EnableAudioCaptureDevicePtr(_gmeInstance, enable ? 1 : 0);
    int ret2 = EnableAudioSendPtr(_gmeInstance, enable ? 1 : 0);
    if (ret1 == 0 && ret2 == 0) {
      return 0;
    } else {
      if (ret1 != 0) {
        return ret1;
      } else {
        return ret2;
      }
    }
  }

  int GetMicState() {
    return (IsAudioCaptureDeviceEnabledPtr(_gmeInstance) == 1 &&
            IsAudioSendEnabledPtr(_gmeInstance) == 1)
        ? 1
        : 0;
  }

  int EnableSpeaker(bool enable) {
    int ret1 = EnableAudioPlayDevicePtr(_gmeInstance, enable ? 1 : 0);
    int ret2 = EnableAudioRecvPtr(_gmeInstance, enable ? 1 : 0);
    if (ret1 == 0 && ret2 == 0) {
      return 0;
    } else {
      if (ret1 != 0) {
        return ret1;
      } else {
        return ret2;
      }
    }
  }

  int GetSpeakerState() {
    return (IsAudioPlayDeviceEnabledPtr(_gmeInstance) == 1 &&
            IsAudioRecvEnabledPtr(_gmeInstance) == 1)
        ? 1
        : 0;
  }

  late final EnableAudioCaptureDeviceDart EnableAudioCaptureDevicePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<EnableAudioCaptureDeviceNative>>(
            'GMEUnity_EnableAudioCaptureDevice',
          )
          .asFunction<EnableAudioCaptureDeviceDart>();

  int EnableAudioCaptureDevice(bool enable) {
    return EnableAudioCaptureDevicePtr(_gmeInstance, enable ? 1 : 0);
  }

  late final IsAudioCaptureDeviceEnabledDart IsAudioCaptureDeviceEnabledPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<IsAudioCaptureDeviceEnabledNative>>(
            'GMEUnity_IsAudioCaptureDeviceEnabled',
          )
          .asFunction<IsAudioCaptureDeviceEnabledDart>();

  bool IsAudioCaptureDeviceEnabled() {
    return (IsAudioCaptureDeviceEnabledPtr(_gmeInstance) == 1);
  }

  late final EnableAudioPlayDeviceDart EnableAudioPlayDevicePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<EnableAudioPlayDeviceNative>>(
            'GMEUnity_EnableAudioPlayDevice',
          )
          .asFunction<EnableAudioPlayDeviceDart>();

  int EnableAudioPlayDevice(bool enable) {
    return EnableAudioPlayDevicePtr(_gmeInstance, enable ? 1 : 0);
  }

  late final IsAudioPlayDeviceEnabledDart IsAudioPlayDeviceEnabledPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<IsAudioPlayDeviceEnabledNative>>(
            'GMEUnity_IsAudioPlayDeviceEnabled',
          )
          .asFunction<IsAudioPlayDeviceEnabledDart>();

  bool IsAudioPlayDeviceEnabled() {
    return IsAudioPlayDeviceEnabledPtr(_gmeInstance) == 1;
  }

  late final EnableAudioSendDart EnableAudioSendPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<EnableAudioSendNative>>(
            'GMEUnity_EnableAudioSend',
          )
          .asFunction<EnableAudioSendDart>();

  int EnableAudioSend(bool enable) {
    return EnableAudioSendPtr(_gmeInstance, enable ? 1 : 0);
  }

  late final IsAudioSendEnabledDart IsAudioSendEnabledPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<IsAudioSendEnabledNative>>(
            'GMEUnity_IsAudioSendEnabled',
          )
          .asFunction<IsAudioSendEnabledDart>();

  bool IsAudioSendEnabled() {
    return IsAudioSendEnabledPtr(_gmeInstance) == 1;
  }

  late final EnableAudioRecvDart EnableAudioRecvPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<EnableAudioRecvNative>>(
            'GMEUnity_EnableAudioRecv',
          )
          .asFunction<EnableAudioRecvDart>();

  int EnableAudioRecv(bool enable) {
    return EnableAudioRecvPtr(_gmeInstance, enable ? 1 : 0);
  }

  late final IsAudioRecvEnabledDart IsAudioRecvEnabledPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<IsAudioRecvEnabledNative>>(
            'GMEUnity_IsAudioRecvEnabled',
          )
          .asFunction<IsAudioRecvEnabledDart>();

  bool IsAudioRecvEnabled() {
    return IsAudioRecvEnabledPtr(_gmeInstance) == 1;
  }

  late final SetMicVolumeDart SetMicVolumePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<SetMicVolumeNative>>('GMEUnity_SetMicVolume')
          .asFunction<SetMicVolumeDart>();

  int SetMicVolume(int volume) {
    return SetMicVolumePtr(_gmeInstance, volume);
  }

  late final GetMicVolumeDart GetMicVolumePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GetMicVolumeNative>>('GMEUnity_GetMicVolume')
          .asFunction<GetMicVolumeDart>();

  int GetMicVolume() {
    return GetMicVolumePtr(_gmeInstance);
  }

  late final SetSpeakerVolumeDart SetSpeakerVolumePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<SetSpeakerVolumeNative>>(
            'GMEUnity_SetSpeakerVolume',
          )
          .asFunction<SetSpeakerVolumeDart>();

  int SetSpeakerVolume(int volume) {
    return SetSpeakerVolumePtr(_gmeInstance, volume);
  }

  late final GetSpeakerVolumeDart GetSpeakerVolumePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GetSpeakerVolumeNative>>(
            'GMEUnity_GetSpeakerVolume',
          )
          .asFunction<GetSpeakerVolumeDart>();

  int GetSpeakerVolume() {
    return GetSpeakerVolumePtr(_gmeInstance);
  }

  late final SetSpeakerVolumeByUserIDDart SetSpeakerVolumeByUserIDPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<SetSpeakerVolumeByUserIDNative>>(
            'GMEUnity_SetSpeakerVolumeByUserID',
          )
          .asFunction<SetSpeakerVolumeByUserIDDart>();

  int SetSpeakerVolumeByUserID(String userID, int volume) {
    return SetSpeakerVolumeByUserIDPtr(
      _gmeInstance,
      userID.toNativeUtf8().cast<Int8>(),
      volume,
    );
  }

  late final GetSpeakerVolumeByUserIDDart GetSpeakerVolumeByUserIDPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GetSpeakerVolumeByUserIDNative>>(
            'GMEUnity_GetSpeakerVolumeByUserID',
          )
          .asFunction<GetSpeakerVolumeByUserIDDart>();

  int GetSpeakerVolumeByUserID(String userID) {
    return GetSpeakerVolumeByUserIDPtr(
      _gmeInstance,
      userID.toNativeUtf8().cast<Int8>(),
    );
  }

  late final EnableLoopBackDart EnableLoopBackPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<EnableLoopBackNative>>(
            'GMEUnity_EnableLoopBack',
          )
          .asFunction<EnableLoopBackDart>();

  int EnableLoopBack(bool enable) {
    return EnableLoopBackPtr(_gmeInstance, enable ? 1 : 0);
  }

  late final SetLoopBackVolumeDart SetLoopBackVolumePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<SetLoopBackVolumeNative>>(
            'GMEUnity_SetLoopBackVolume',
          )
          .asFunction<SetLoopBackVolumeDart>();

  int SetLoopBackVolume(int volume) {
    return SetLoopBackVolumePtr(_gmeInstance, volume);
  }

  late final AddAudioBlackListDart AddAudioBlackListPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<AddAudioBlackListNative>>(
            'GMEUnity_AddAudioBlackList',
          )
          .asFunction<AddAudioBlackListDart>();

  int AddAudioBlackList(String userID) {
    return AddAudioBlackListPtr(
      _gmeInstance,
      userID.toNativeUtf8().cast<Int8>(),
    );
  }

  late final RemoveAudioBlackListDart RemoveAudioBlackListPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<RemoveAudioBlackListNative>>(
            'GMEUnity_RemoveAudioBlackList',
          )
          .asFunction<RemoveAudioBlackListDart>();

  int RemoveAudioBlackList(String userID) {
    return RemoveAudioBlackListPtr(
      _gmeInstance,
      userID.toNativeUtf8().cast<Int8>(),
    );
  }

  late final IsUserIDInAudioBlackListDart IsUserIDInAudioBlackListPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<IsUserIDInAudioBlackListNative>>(
            'GMEUnity_IsUserIDInAudioBlackList',
          )
          .asFunction<IsUserIDInAudioBlackListDart>();

  bool IsUserIDInAudioBlackList(String userID) {
    return IsUserIDInAudioBlackListPtr(
          _gmeInstance,
          userID.toNativeUtf8().cast<Int8>(),
        ) ==
        1;
  }

  late final EnableSpatializerDart EnableSpatializerPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<EnableSpatializerNative>>(
            'GMEUnity_EnableSpatializer',
          )
          .asFunction<EnableSpatializerDart>();

  int EnableSpatializer(bool enable) {
    return EnableSpatializerPtr(_gmeInstance, enable ? 1 : 0);
  }

  late final IsEnableSpatializerDart IsEnableSpatializerPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<IsEnableSpatializerNative>>(
            'GMEUnity_IsEnableSpatializer',
          )
          .asFunction<IsEnableSpatializerDart>();

  bool IsEnableSpatializer() {
    return IsEnableSpatializerPtr(_gmeInstance) == 1;
  }

  late final TrackingVolumeDart TrackingVolumePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<TrackingVolumeNative>>(
            'GMEUnity_TrackingVolume',
          )
          .asFunction<TrackingVolumeDart>();

  int TrackingVolume(double interval) {
    return TrackingVolumePtr(_gmeInstance, interval);
  }

  late final StopTrackingVolumeDart StopTrackingVolumePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<StopTrackingVolumeNative>>(
            'GMEUnity_StopTrackingVolume',
          )
          .asFunction<StopTrackingVolumeDart>();

  int StopTrackingVolume() {
    return StopTrackingVolumePtr(_gmeInstance);
  }

  late final GetMicLevelDart GetMicLevelPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GetMicLevelNative>>('GMEUnity_GetMicLevel')
          .asFunction<GetMicLevelDart>();

  int GetMicLevel() {
    return GetMicLevelPtr(_gmeInstance);
  }

  late final GetSpeakerLevelDart GetSpeakerLevelPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GetSpeakerLevelNative>>(
            'GMEUnity_GetSpeakerLevel',
          )
          .asFunction<GetSpeakerLevelDart>();

  int GetSpeakerLevel() {
    return GetSpeakerLevelPtr(_gmeInstance);
  }

  late final GetSendStreamLevelDart GetSendStreamLevelPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GetSendStreamLevelNative>>(
            'GMEUnity_GetSendStreamLevel',
          )
          .asFunction<GetSendStreamLevelDart>();

  int GetSendStreamLevel() {
    return GetSendStreamLevelPtr(_gmeInstance);
  }

  late final GetRecvStreamLevelDart GetRecvStreamLevelPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GetRecvStreamLevelNative>>(
            'GMEUnity_GetRecvStreamLevel',
          )
          .asFunction<GetRecvStreamLevelDart>();

  int GetRecvStreamLevel(String userID) {
    return GetRecvStreamLevelPtr(
      _gmeInstance,
      userID.toNativeUtf8().cast<Int8>(),
    );
  }
}
