import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'tmg_load_dynamic.dart';

typedef EnableAudioCaptureDeviceNative = Int32 Function(Int8 enable);
typedef EnableAudioCaptureDeviceDart = int Function(int enable);

typedef IsAudioCaptureDeviceEnabledNative = Int8 Function();
typedef IsAudioCaptureDeviceEnabledDart = int Function();

typedef EnableAudioPlayDeviceNative = Int32 Function(Int8 enable);
typedef EnableAudioPlayDeviceDart = int Function(int enable);

typedef IsAudioPlayDeviceEnabledNative = Int8 Function();
typedef IsAudioPlayDeviceEnabledDart = int Function();

typedef EnableAudioSendNative = Int32 Function(Int8 enable);
typedef EnableAudioSendDart = int Function(int enable);

typedef IsAudioSendEnabledNative = Int8 Function();
typedef IsAudioSendEnabledDart = int Function();

typedef EnableAudioRecvNative = Int32 Function(Int8 enable);
typedef EnableAudioRecvDart = int Function(int enable);

typedef IsAudioRecvEnabledNative = Int8 Function();
typedef IsAudioRecvEnabledDart = int Function();

typedef SetMicVolumeNative = Int32 Function(Int32 volume);
typedef SetMicVolumeDart = int Function(int volume);

typedef GetMicVolumeNative = Int32 Function();
typedef GetMicVolumeDart = int Function();

typedef EnableLoopBackNative = Int32 Function(Int8 enable);
typedef EnableLoopBackDart = int Function(int enable);

typedef TrackingVolumeNative = Int32 Function(Float interval);
typedef TrackingVolumeDart = int Function(double interval);

typedef StopTrackingVolumeNative = Int32 Function();
typedef StopTrackingVolumeDart = int Function();

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

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

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

class TMGAudioCtrlBindings {
  DynamicLibrary? _gmeSdkLib = null;
  TMGLoadDynamic _tmgDynamicInstance = TMGLoadDynamic.GetInstance();
  TMGAudioCtrlBindings() {
    _gmeSdkLib = _tmgDynamicInstance.GetGmeSdkLib();
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  int GetMicVolume() {
    return GetMicVolumePtr();
  }

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

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

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

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

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

  int StopTrackingVolume() {
    return StopTrackingVolumePtr();
  }

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

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

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

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

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

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