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

typedef CreateInstanceNative = Pointer<Void> Function();

typedef SetDelegateNative =
    Void Function(
      Pointer<Void> ins,
      Pointer<NativeFunction<AVEventCallback_CSharp>> onEventCallback,
    );
typedef SetDelegateDart =
    void Function(
      Pointer<Void> ins,
      Pointer<NativeFunction<AVEventCallback_CSharp>> onEventCallback,
    );

typedef GMESetRegionNative = Void Function(Pointer<Void>, Pointer<Int8> region);
typedef GMESetRegionDart = void Function(Pointer<Void>, Pointer<Int8> region);

typedef GMEInitNative =
    Int32 Function(
      Pointer<Void>,
      Pointer<Int8> sdk_app_id,
      Pointer<Int8> user_id,
    );
typedef GMEInitDart =
    int Function(
      Pointer<Void>,
      Pointer<Int8> sdk_app_id,
      Pointer<Int8> user_id,
    );

typedef GMEPollNative = Int32 Function(Pointer<Void>);
typedef GMEPollDart = int Function(Pointer<Void>);

typedef GMEPauseNative = Int32 Function(Pointer<Void>);
typedef GMEPauseDart = int Function(Pointer<Void>);

typedef GMEResumeNative = Int32 Function(Pointer<Void>);
typedef GMEResumeDart = int Function(Pointer<Void>);

typedef GMEUninitNative = Int32 Function(Pointer<Void>);
typedef GMEUninitDart = int Function(Pointer<Void>);

typedef GMESetSceneNative = Int32 Function(Pointer<Void>, Int32 scene);
typedef GMESetSceneDart = int Function(Pointer<Void>, int scene);

typedef GMESetAudioRoleNative = Int32 Function(Pointer<Void>, Int32 role);
typedef GMESetAudioRoleDart = int Function(Pointer<Void>, int role);

typedef GMESetRangeAudioModeNative =
    Int32 Function(Pointer<Void>, Int32 rangeAudioMode);
typedef GMESetRangeAudioModeDart =
    int Function(Pointer<Void>, int rangeAudioMode);

typedef GMESetRangeAudioTeamIDNative =
    Int32 Function(Pointer<Void>, Int32 teamID);
typedef GMESetRangeAudioTeamIDDart = int Function(Pointer<Void>, int teamID);

typedef GenAuthBufferNative =
    Int32 Function(
      Int32 appId,
      Pointer<Int8> roomId,
      Pointer<Int8> userId,
      Pointer<Int8> key,
      Pointer<Int8> authBuffer,
      Int32 authBufferLen,
    );
typedef GenAuthBufferDart =
    int Function(
      int appId,
      Pointer<Int8> roomId,
      Pointer<Int8> userId,
      Pointer<Int8> key,
      Pointer<Int8> authBuffer,
      int authBufferLen,
    );

typedef GMEEnterRoomNative =
    Int32 Function(
      Pointer<Void>,
      Pointer<Int8> room_id,
      Int32 room_type,
      Pointer<Int8> user_sig,
    );
typedef GMEEnterRoomDart =
    int Function(
      Pointer<Void>,
      Pointer<Int8> room_id,
      int room_type,
      Pointer<Int8> user_sig,
    );

typedef GMEExitRoomNative = Int32 Function(Pointer<Void>);
typedef GMEExitRoomDart = int Function(Pointer<Void>);

typedef GMEIsRoomEnteredNative = Int8 Function(Pointer<Void>);
typedef GMEIsRoomEnteredDart = int Function(Pointer<Void>);

typedef SetLogLevelNative =
    Int32 Function(Pointer<Void>, Int32 levelWrite, Int32 levelPrint);
typedef SetLogLevelDart =
    int Function(Pointer<Void>, int levelWrite, int levelPrint);

typedef SetLogPathNative = Int32 Function(Pointer<Void>, Pointer<Int8> logDir);
typedef SetLogPathDart = int Function(Pointer<Void>, Pointer<Int8> logDir);

typedef GetLogPathNative = Pointer<Int8> Function(Pointer<Void>);
typedef GetLogPathDart = Pointer<Int8> Function(Pointer<Void>);

typedef GetSDKVersionNative = Pointer<Int8> Function(Pointer<Void>);
typedef GetSDKVersionDart = Pointer<Int8> Function(Pointer<Void>);

typedef SetAppVersionNative =
    Void Function(Pointer<Void>, Pointer<Int8> appVersion);
typedef SetAppVersionDart =
    void Function(Pointer<Void>, Pointer<Int8> appVersion);

typedef ShowDebugViewNative = Int32 Function(Pointer<Void>, Int8 show);
typedef ShowDebugViewDart = int Function(Pointer<Void>, int show);

typedef SetAdvanceParamsNative =
    Int32 Function(Pointer<Void>, Pointer<Int8> key, Pointer<Int8> value);
typedef SetAdvanceParamsDart =
    int Function(Pointer<Void>, Pointer<Int8> key, Pointer<Int8> value);

typedef GetAdvanceParamsNative =
    Pointer<Int8> Function(Pointer<Void>, Pointer<Int8> key);
typedef GetAdvanceParamsDart =
    Pointer<Int8> Function(Pointer<Void>, Pointer<Int8> key);

typedef CheckMicPermissionNative = Int32 Function(Pointer<Void>);
typedef CheckMicPermissionDart = int Function(Pointer<Void>);

typedef AVEventCallback_CSharp =
    Void Function(
      Pointer<Void> api_proxy_holder,
      Int32 event_type,
      Pointer<Int8> data,
    );
typedef AVEventCallback =
    void Function(
      Pointer<Void> api_proxy_holder,
      int event_type,
      Pointer<Int8> data,
    );

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

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

  late final Pointer<Void> Function() CreateInstancePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<CreateInstanceNative>>(
            'GMEUnity_CreateInstance',
          )
          .asFunction<Pointer<Void> Function()>();

  void CreateInstance() {
    _gmeInstance = CreateInstancePtr();
  }

  late final SetDelegateDart SetDelegatePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<SetDelegateNative>>('GMEUnity_SetDelegate')
          .asFunction<SetDelegateDart>();

  int SetDelegate(
    Pointer<NativeFunction<AVEventCallback_CSharp>> onEventCallback,
  ) {
    SetDelegatePtr(_gmeInstance, onEventCallback);
    return 0;
  }

  late final GMESetRegionDart SetRegionPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMESetRegionNative>>('GMEUnity_SetRegion')
          .asFunction<GMESetRegionDart>();

  int SetRegion(String region) {
    SetRegionPtr(_gmeInstance, region.toNativeUtf8().cast<Int8>());
    return 0;
  }

  late final GMEInitDart InitPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMEInitNative>>('GMEUnity_Init')
          .asFunction<GMEInitDart>();

  int Init(String sdk_app_id, String user_id) {
    return InitPtr(
      _gmeInstance,
      sdk_app_id.toNativeUtf8().cast<Int8>(),
      user_id.toNativeUtf8().cast<Int8>(),
    );
  }

  late final GMEPollDart PollPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMEPollNative>>('GMEUnity_Poll')
          .asFunction<GMEPollDart>();

  int Poll() {
    return PollPtr(_gmeInstance);
  }

  late final GMEPauseDart PausePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMEPauseNative>>('GMEUnity_Pause')
          .asFunction<GMEPauseDart>();

  int Pause() {
    return PausePtr(_gmeInstance);
  }

  late final GMEResumeDart ResumePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMEResumeNative>>('GMEUnity_Resume')
          .asFunction<GMEResumeDart>();

  int Resume() {
    return ResumePtr(_gmeInstance);
  }

  late final GMEUninitDart UninitPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMEUninitNative>>('GMEUnity_Uninit')
          .asFunction<GMEUninitDart>();

  int Uninit() {
    return UninitPtr(_gmeInstance);
  }

  late final GMESetSceneDart SetScenePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMESetSceneNative>>('GMEUnity_SetScene')
          .asFunction<GMESetSceneDart>();

  int SetScene(int scene) {
    return SetScenePtr(_gmeInstance, scene);
  }

  late final GMESetAudioRoleDart SetAudioRolePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMESetAudioRoleNative>>(
            'GMEUnity_SetAudioRole',
          )
          .asFunction<GMESetAudioRoleDart>();

  int SetAudioRole(int role) {
    return SetAudioRolePtr(_gmeInstance, role);
  }

  late final GMESetRangeAudioModeDart SetRangeAudioModePtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMESetRangeAudioModeNative>>(
            'GMEUnity_SetRangeAudioMode',
          )
          .asFunction<GMESetRangeAudioModeDart>();

  int SetRangeAudioMode(int rangeAudioMode) {
    return SetRangeAudioModePtr(_gmeInstance, rangeAudioMode);
  }

  late final GMESetRangeAudioTeamIDDart SetRangeAudioTeamIDPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMESetRangeAudioTeamIDNative>>(
            'GMEUnity_SetRangeAudioTeamID',
          )
          .asFunction<GMESetRangeAudioTeamIDDart>();

  int SetRangeAudioTeamID(int teamID) {
    return SetRangeAudioTeamIDPtr(_gmeInstance, teamID);
  }

  late final GenAuthBufferDart GenAuthBufferPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GenAuthBufferNative>>(
            'QAVSDK_AuthBuffer_GenAuthBuffer',
          )
          .asFunction<GenAuthBufferDart>();

  String GenAuthBuffer(int appId, String roomId, String userId, String key) {
    final int authBufferSize = 1024;
    final authBuffer = calloc<Int8>(authBufferSize);
    int ret = GenAuthBufferPtr(
      appId,
      roomId.toNativeUtf8().cast<Int8>(),
      userId.toNativeUtf8().cast<Int8>(),
      key.toNativeUtf8().cast<Int8>(),
      authBuffer,
      authBufferSize,
    );
    String result = authBuffer.cast<Utf8>().toDartString();
    calloc.free(authBuffer);
    return result;
  }

  late final GMEEnterRoomDart EnterRoomPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMEEnterRoomNative>>('GMEUnity_EnterRoom')
          .asFunction<GMEEnterRoomDart>();

  int EnterRoom(String room_id, int room_type, String user_sig) {
    return EnterRoomPtr(
      _gmeInstance,
      room_id.toNativeUtf8().cast<Int8>(),
      room_type,
      user_sig.toNativeUtf8().cast<Int8>(),
    );
  }

  late final GMEExitRoomDart ExitRoomPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMEExitRoomNative>>('GMEUnity_ExitRoom')
          .asFunction<GMEExitRoomDart>();

  int ExitRoom() {
    return ExitRoomPtr(_gmeInstance);
  }

  late final GMEIsRoomEnteredDart IsRoomEnteredPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GMEIsRoomEnteredNative>>(
            'GMEUnity_IsRoomEntered',
          )
          .asFunction<GMEIsRoomEnteredDart>();

  bool IsRoomEntered() {
    return (IsRoomEnteredPtr(_gmeInstance) == 1);
  }

  late final SetLogLevelDart SetLogLevelPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<SetLogLevelNative>>('GMEUnity_SetLogLevel')
          .asFunction<SetLogLevelDart>();

  int SetLogLevel(int levelWrite, int levelPrint) {
    return SetLogLevelPtr(_gmeInstance, levelWrite, levelPrint);
  }

  late final SetLogPathDart SetLogPathPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<SetLogPathNative>>('GMEUnity_SetLogPath')
          .asFunction<SetLogPathDart>();

  int SetLogPath(String logDir) {
    return SetLogPathPtr(_gmeInstance, logDir.toNativeUtf8().cast<Int8>());
  }

  late final GetLogPathDart GetLogPathPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GetLogPathNative>>('GMEUnity_GetLogPath')
          .asFunction<GetLogPathDart>();

  String GetLogPath() {
    return GetLogPathPtr(_gmeInstance).cast<Utf8>().toDartString();
  }

  late final GetSDKVersionDart GetSDKVersionPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GetSDKVersionNative>>('GMEUnity_GetSDKVersion')
          .asFunction<GetSDKVersionDart>();

  String GetSDKVersion() {
    return GetSDKVersionPtr(_gmeInstance).cast<Utf8>().toDartString();
  }

  late final SetAppVersionDart SetAppVersionPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<SetAppVersionNative>>('GMEUnity_SetAppVersion')
          .asFunction<SetAppVersionDart>();

  void SetAppVersion(String appVersion) {
    SetAppVersionPtr(_gmeInstance, appVersion.toNativeUtf8().cast<Int8>());
  }

  late final ShowDebugViewDart ShowDebugViewPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<ShowDebugViewNative>>('GMEUnity_ShowDebugView')
          .asFunction<ShowDebugViewDart>();

  int ShowDebugView(bool show) {
    ShowDebugViewPtr(_gmeInstance, show ? 1 : 0);
    return 0;
  }

  late final SetAdvanceParamsDart SetAdvanceParamsPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<SetAdvanceParamsNative>>(
            'GMEUnity_SetAdvanceParams',
          )
          .asFunction<SetAdvanceParamsDart>();

  int SetAdvanceParams(String key, String value) {
    return SetAdvanceParamsPtr(
      _gmeInstance,
      key.toNativeUtf8().cast<Int8>(),
      value.toNativeUtf8().cast<Int8>(),
    );
  }

  late final GetAdvanceParamsDart GetAdvanceParamsPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<GetAdvanceParamsNative>>(
            'GMEUnity_GetAdvanceParams',
          )
          .asFunction<GetAdvanceParamsDart>();

  String GetAdvanceParams(String key) {
    return GetAdvanceParamsPtr(
      _gmeInstance,
      key.toNativeUtf8().cast<Int8>(),
    ).cast<Utf8>().toDartString();
  }

  late final CheckMicPermissionDart CheckMicPermissionPtr =
      _gmeSdkLib!
          .lookup<NativeFunction<CheckMicPermissionNative>>(
            'GMEUnity_CheckMicPermission',
          )
          .asFunction<CheckMicPermissionDart>();
  int CheckMicPermission() {
    return CheckMicPermissionPtr(_gmeInstance);
  }
}
