/**
 * @file MaaDef.h
 * @author
 * @brief The type definitions.
 *
 * @copyright Copyright (c) 2024
 *
 */

// IWYU pragma: private, include <MaaFramework/MaaAPI.h>

#pragma once

#include <stdint.h>

#include "MaaPort.h" // IWYU pragma: export

typedef uint8_t MaaBool;
typedef uint64_t MaaSize;
#define MaaNullSize UINT64_MAX

typedef int64_t MaaId;
typedef MaaId MaaCtrlId;
typedef MaaId MaaResId;
typedef MaaId MaaTaskId;
typedef MaaId MaaRecoId;
typedef MaaId MaaActId;
typedef MaaId MaaNodeId;
typedef MaaId MaaWfId;
typedef MaaId MaaSinkId;
#define MaaInvalidId ((MaaId)0)

typedef struct MaaStringBuffer MaaStringBuffer;
typedef struct MaaImageBuffer MaaImageBuffer;
typedef struct MaaStringListBuffer MaaStringListBuffer;
typedef struct MaaImageListBuffer MaaImageListBuffer;

typedef struct MaaResource MaaResource;
typedef struct MaaController MaaController;
typedef struct MaaTasker MaaTasker;
typedef struct MaaContext MaaContext;

typedef int32_t MaaStatus;

enum MaaStatusEnum
{
    MaaStatus_Invalid = 0,
    MaaStatus_Pending = 1000,
    MaaStatus_Running = 2000,
    MaaStatus_Succeeded = 3000,
    MaaStatus_Failed = 4000,
    // MaaStatus_Timeout = 5000,
};

typedef int32_t MaaLoggingLevel;

enum MaaLoggingLevelEnum
{
    MaaLoggingLevel_Off = 0,
    MaaLoggingLevel_Fatal = 1,
    MaaLoggingLevel_Error = 2,
    MaaLoggingLevel_Warn = 3,
    MaaLoggingLevel_Info = 4,
    MaaLoggingLevel_Debug = 5,
    MaaLoggingLevel_Trace = 6,
    MaaLoggingLevel_All = 7,
};

typedef int32_t MaaOption;
typedef void* MaaOptionValue;
typedef uint64_t MaaOptionValueSize;

typedef MaaOption MaaGlobalOption;

enum MaaGlobalOptionEnum
{
    MaaGlobalOption_Invalid = 0,

    /// Log dir
    ///
    /// value: string, eg: "C:\\Users\\Administrator\\Desktop\\log"; val_size: string length
    MaaGlobalOption_LogDir = 1,

    /// Whether to save draw
    ///
    /// value: bool, eg: true; val_size: sizeof(bool)
    MaaGlobalOption_SaveDraw = 2,

    // Deprecated
    // Dump all screenshots and actions
    //
    // Recording will evaluate to true if any of this or MaaCtrlOptionEnum::MaaCtrlOption_Recording is true.
    // value: bool, eg: true; val_size: sizeof(bool)
    // MaaGlobalOption_Recording = 3,

    /// The level of log output to stdout
    ///
    /// value: MaaLoggingLevel, val_size: sizeof(MaaLoggingLevel)
    /// default value is MaaLoggingLevel_Error
    MaaGlobalOption_StdoutLevel = 4,

    // Deprecated
    // Whether to show hit draw
    //
    // value: bool, eg: true; val_size: sizeof(bool)
    // MaaGlobalOption_ShowHitDraw = 5,

    /// Whether to debug
    ///
    /// value: bool, eg: true; val_size: sizeof(bool)
    MaaGlobalOption_DebugMode = 6,

    /// Whether to save screenshot on error
    ///
    /// value: bool, eg: true; val_size: sizeof(bool)
    MaaGlobalOption_SaveOnError = 7,

    /// Image quality for draw images
    ///
    /// value: int, eg: 85; val_size: sizeof(int)
    /// default value is 85, range: [0, 100]
    MaaGlobalOption_DrawQuality = 8,

    /// Recognition image cache limit
    ///
    /// value: size_t, eg: 4096; val_size: sizeof(size_t)
    /// default value is 4096
    MaaGlobalOption_RecoImageCacheLimit = 9,
};

typedef MaaOption MaaResOption;

typedef int32_t MaaInferenceDevice;
typedef int32_t MaaInferenceExecutionProvider;

enum MaaInferenceDeviceEnum
{
    MaaInferenceDevice_CPU = -2,
    MaaInferenceDevice_Auto = -1,
    MaaInferenceDevice_0 = 0,
    MaaInferenceDevice_1 = 1,
    // and more gpu id or flag...
};

enum MaaInferenceExecutionProviderEnum
{
    // I don't recommend setting up MaaResOption_InferenceDevice in this case,
    // because you don't know which EP will be used on different user devices.
    MaaInferenceExecutionProvider_Auto = 0,

    // MaaResOption_InferenceDevice will not work.
    MaaInferenceExecutionProvider_CPU = 1,

    // MaaResOption_InferenceDevice will be used to set adapter id,
    // It's from Win32 API `EnumAdapters1`.
    MaaInferenceExecutionProvider_DirectML = 2,

    // MaaResOption_InferenceDevice will be used to set coreml_flag,
    // Reference to
    // https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/providers/coreml/coreml_provider_factory.h
    // But you need to pay attention to the onnxruntime version we use, the latest flag may not be supported.
    MaaInferenceExecutionProvider_CoreML = 3,

    // MaaResOption_InferenceDevice will be used to set NVIDIA GPU ID
    // TODO!
    MaaInferenceExecutionProvider_CUDA = 4,
};

enum MaaResOptionEnum
{
    MaaResOption_Invalid = 0,

    /// Use the specified inference device.
    /// Please set this option before loading the model.
    ///
    /// value: MaaInferenceDevice, eg: 0; val_size: sizeof(MaaInferenceDevice)
    /// default value is MaaInferenceDevice_Auto
    MaaResOption_InferenceDevice = 1,

    /// Use the specified inference execution provider
    /// Please set this option before loading the model.
    ///
    /// value: MaaInferenceExecutionProvider, eg: 0; val_size: sizeof(MaaInferenceExecutionProvider)
    /// default value is MaaInferenceExecutionProvider_Auto
    MaaResOption_InferenceExecutionProvider = 2,
};

typedef MaaOption MaaCtrlOption;

/**
 * @brief Option keys for controller instance options. See MaaControllerSetOption().
 *
 */
enum MaaCtrlOptionEnum
{
    MaaCtrlOption_Invalid = 0,

    /// Only one of long and short side can be set, and the other is automatically scaled according to the aspect ratio.
    ///
    /// value: int, eg: 1280; val_size: sizeof(int)
    MaaCtrlOption_ScreenshotTargetLongSide = 1,

    /// Only one of long and short side can be set, and the other is automatically scaled according to the aspect ratio.
    ///
    /// value: int, eg: 720; val_size: sizeof(int)
    MaaCtrlOption_ScreenshotTargetShortSide = 2,

    /// Screenshot use raw size without scaling.
    /// Please note that this option may cause incorrect coordinates on user devices with different resolutions if scaling is not performed.
    ///
    /// value: bool, eg: true; val_size: sizeof(bool)
    MaaCtrlOption_ScreenshotUseRawSize = 3,

    /// Enable or disable mouse-lock-follow mode for Win32 controllers.
    /// This is designed for TPS/FPS games that lock the mouse to their window in the background.
    /// Only valid for Win32 controllers using message-based input methods.
    ///
    /// value: bool, eg: true; val_size: sizeof(bool)
    MaaCtrlOption_MouseLockFollow = 4,

    // Deprecated
    // Dump all screenshots and actions
    //
    // Recording will evaluate to true if any of this or
    // MaaGlobalOptionEnum::MaaGlobalOption_Recording is true.
    //
    // value: bool, eg: true; val_size: sizeof(bool)
    // MaaCtrlOption_Recording = 5,

    /// Set the interpolation method used when resizing screenshots.
    /// Value corresponds to cv::InterpolationFlags:
    ///   INTER_NEAREST=0, INTER_LINEAR=1, INTER_CUBIC=2, INTER_AREA=3, INTER_LANCZOS4=4
    /// Default is INTER_AREA (3).
    ///
    /// value: int, eg: 3; val_size: sizeof(int)
    MaaCtrlOption_ScreenshotResizeMethod = 6,

    /// Configure background managed key domain for Win32 controllers.
    /// Must be set before connection. After setting, matching ClickKey / LongPressKey / KeyDown / KeyUp
    /// operations automatically route through the background guardian path.
    /// Only supported by Win32 controllers; other controllers will fail.
    ///
    /// value: int32_t array of virtual key codes; val_size: sizeof(int32_t) * count
    MaaCtrlOption_BackgroundManagedKeys = 7,
};

typedef MaaOption MaaTaskerOption;

enum MaaTaskerOptionEnum
{
    MaaTaskerOption_Invalid = 0,
};

// MaaAdbScreencapMethod:
/**
 * @brief Adb screencap method flags
 *
 * Use bitwise OR to set the methods you need.
 * MaaFramework will test all provided methods and use the fastest available one.
 *
 * Default: All methods except RawByNetcat, MinicapDirect, MinicapStream
 *
 * Note: MinicapDirect and MinicapStream use lossy JPEG encoding, which may
 * significantly reduce template matching accuracy. Not recommended.
 *
 * | Method                | Speed      | Compatibility | Encoding | Notes                             |
 * |-----------------------|------------|---------------|----------|-----------------------------------|
 * | EncodeToFileAndPull   | Slow       | High          | Lossless |                                   |
 * | Encode                | Slow       | High          | Lossless |                                   |
 * | RawWithGzip           | Medium     | High          | Lossless |                                   |
 * | RawByNetcat           | Fast       | Low           | Lossless |                                   |
 * | MinicapDirect         | Fast       | Low           | Lossy    |                                   |
 * | MinicapStream         | Very Fast  | Low           | Lossy    |                                   |
 * | EmulatorExtras        | Very Fast  | Low           | Lossless | Emulators only: MuMu 12, LDPlayer 9 |
 */
typedef uint64_t MaaAdbScreencapMethod;
#define MaaAdbScreencapMethod_EncodeToFileAndPull 1ULL
#define MaaAdbScreencapMethod_Encode (1ULL << 1)
#define MaaAdbScreencapMethod_RawWithGzip (1ULL << 2)
#define MaaAdbScreencapMethod_RawByNetcat (1ULL << 3)
#define MaaAdbScreencapMethod_MinicapDirect (1ULL << 4)
#define MaaAdbScreencapMethod_MinicapStream (1ULL << 5)
#define MaaAdbScreencapMethod_EmulatorExtras (1ULL << 6)

#define MaaAdbScreencapMethod_None 0ULL
#define MaaAdbScreencapMethod_All (~MaaAdbScreencapMethod_None)
#define MaaAdbScreencapMethod_Default                                                                          \
    (MaaAdbScreencapMethod_All & (~MaaAdbScreencapMethod_RawByNetcat) & (~MaaAdbScreencapMethod_MinicapDirect) \
     & (~MaaAdbScreencapMethod_MinicapStream))

// MaaAdbInputMethod:
/**
 * @brief Adb input method flags
 *
 * Use bitwise OR to set the methods you need.
 * MaaFramework will select the first available method according to priority.
 *
 * Priority (high to low): EmulatorExtras > Maatouch > MinitouchAndAdbKey > AdbShell
 *
 * Default: All methods except EmulatorExtras
 *
 * | Method               | Speed | Compatibility | Notes                                 |
 * |----------------------|-------|---------------|---------------------------------------|
 * | AdbShell             | Slow  | High          |                                       |
 * | MinitouchAndAdbKey   | Fast  | Medium        | Key press still uses AdbShell         |
 * | Maatouch             | Fast  | Medium        |                                       |
 * | EmulatorExtras       | Fast  | Low           | Emulators only: MuMu 12               |
 */
typedef uint64_t MaaAdbInputMethod;
#define MaaAdbInputMethod_AdbShell 1ULL
#define MaaAdbInputMethod_MinitouchAndAdbKey (1ULL << 1)
#define MaaAdbInputMethod_Maatouch (1ULL << 2)
#define MaaAdbInputMethod_EmulatorExtras (1ULL << 3)

#define MaaAdbInputMethod_None 0ULL
#define MaaAdbInputMethod_All (~MaaAdbInputMethod_None)
#define MaaAdbInputMethod_Default (MaaAdbInputMethod_All & (~MaaAdbInputMethod_EmulatorExtras))

// MaaWin32ScreencapMethod:
/**
 * @brief Win32 screencap method flags
 *
 * Use bitwise OR to set the methods you need.
 * MaaFramework will test all provided methods and use the fastest available one.
 *
 * No default value. Client should choose one as default.
 *
 * Predefined combinations:
 * - Foreground: DXGI_DesktopDup_Window | ScreenDC
 * - Background: FramePool | PrintWindow
 *
 * Different applications use different rendering methods, there is no universal solution.
 *
 * | Method                  | Speed     | Compatibility | Require Admin | Background Support | Notes                            |
 * |-------------------------|-----------|---------------|---------------|--------------------|----------------------------------|
 * | GDI                     | Fast      | Medium        | No            | No                 |                                  |
 * | FramePool               | Very Fast | Medium        | No            | Yes                | Requires Windows 10 1903+        |
 * | DXGI_DesktopDup         | Very Fast | Low           | No            | No                 | Desktop duplication (full screen)|
 * | DXGI_DesktopDup_Window  | Very Fast | Low           | No            | No                 | Desktop duplication then crop    |
 * | PrintWindow             | Medium    | Medium        | No            | Yes                |                                  |
 * | ScreenDC                | Fast      | High          | No            | No                 |                                  |
 *
 * Note: FramePool and PrintWindow support pseudo-minimize — when the target window
 * is minimized, they make it transparent and click-through, then restore it without
 * activation, allowing screencap to continue without disturbing the user.
 * Other screencap methods will fail when the target window is minimized.
 */
typedef uint64_t MaaWin32ScreencapMethod;
#define MaaWin32ScreencapMethod_None 0ULL
#define MaaWin32ScreencapMethod_GDI 1ULL
#define MaaWin32ScreencapMethod_FramePool (1ULL << 1)
#define MaaWin32ScreencapMethod_DXGI_DesktopDup (1ULL << 2)
#define MaaWin32ScreencapMethod_DXGI_DesktopDup_Window (1ULL << 3)
#define MaaWin32ScreencapMethod_PrintWindow (1ULL << 4)
#define MaaWin32ScreencapMethod_ScreenDC (1ULL << 5)

#define MaaWin32ScreencapMethod_All (~MaaWin32ScreencapMethod_None)
#define MaaWin32ScreencapMethod_Foreground (MaaWin32ScreencapMethod_DXGI_DesktopDup_Window | MaaWin32ScreencapMethod_ScreenDC)
#define MaaWin32ScreencapMethod_Background (MaaWin32ScreencapMethod_FramePool | MaaWin32ScreencapMethod_PrintWindow)

// MaaWin32InputMethod:
/**
 * @brief Win32 input method
 *
 * No bitwise OR, select ONE method only.
 *
 * No default value. Client should choose one as default.
 *
 * Different applications process input differently, there is no universal solution.
 *
 * | Method                       | Compatibility | Require Admin | Seize Mouse  | Background Support | Notes |
 * |------------------------------|---------------|---------------|--------------|--------------------|-------------------------------------------------------------
 * | | Seize                        | High          | No            | Yes          | No                 | | | SendMessage                  |
 * Medium        | Maybe         | No           | Yes                |                                                             | |
 * PostMessage                  | Medium        | Maybe         | No           | Yes                | | | LegacyEvent                  | Low
 * | No            | Yes          | No                 |                                                             | | PostThreadMessage
 * | Low           | Maybe         | No           | Yes                |                                                             | |
 * SendMessageWithCursorPos     | Medium        | Maybe         | Briefly      | Yes                | Moves cursor to target position, then
 * restores              | | PostMessageWithCursorPos     | Medium        | Maybe         | Briefly      | Yes                | Moves cursor
 * to target position, then restores              | | SendMessageWithWindowPos     | Medium        | Maybe         | No           | Yes |
 * Moves window to align target with cursor, then restores     | | PostMessageWithWindowPos     | Medium        | Maybe         | No | Yes |
 * Moves window to align target with cursor, then restores     |
 *
 * Note:
 * - Admin rights mainly depend on the target application's privilege level.
 *   If the target runs as admin, MaaFramework should also run as admin for compatibility.
 * - "WithCursorPos" methods briefly move the cursor to target position, send message,
 *   then restore cursor position. This "briefly" seizes the mouse but won't block user operations.
 * - "WithWindowPos" methods briefly move the window so the target aligns with the current cursor
 *   position, send message, then restore the window position. The cursor is not moved.
 */
typedef uint64_t MaaWin32InputMethod;
#define MaaWin32InputMethod_None 0ULL
#define MaaWin32InputMethod_Seize 1ULL
#define MaaWin32InputMethod_SendMessage (1ULL << 1)
#define MaaWin32InputMethod_PostMessage (1ULL << 2)
#define MaaWin32InputMethod_LegacyEvent (1ULL << 3)
#define MaaWin32InputMethod_PostThreadMessage (1ULL << 4) // Deprecated
#define MaaWin32InputMethod_SendMessageWithCursorPos (1ULL << 5)
#define MaaWin32InputMethod_PostMessageWithCursorPos (1ULL << 6)
#define MaaWin32InputMethod_SendMessageWithWindowPos (1ULL << 7)
#define MaaWin32InputMethod_PostMessageWithWindowPos (1ULL << 8)

// MaaMacOSScreencapMethod:
/**
 * @brief macOS screencap method
 *
 * Select ONE method only.
 *
 * | Method          | Description                                    |
 * |-----------------|------------------------------------------------|
 * | ScreenCaptureKit| Modern macOS screencap using ScreenCaptureKit  |
 */
typedef uint64_t MaaMacOSScreencapMethod;
#define MaaMacOSScreencapMethod_None 0ULL
#define MaaMacOSScreencapMethod_ScreenCaptureKit 1ULL
// TODO Core Graphics method?

// MaaMacOSInputMethod:
/**
 * @brief macOS input method
 *
 * Select ONE method only.
 *
 * | Method          | Description                                    |
 * |-----------------|------------------------------------------------|
 * | GlobalEvent     | Injects into the global HID event stream via CGEventPost(kCGHIDEventTap), dispatched by the OS to the front window |
 * | PostToPid       | Directly send to target process using CGEventPostToPid |
 */
typedef uint64_t MaaMacOSInputMethod;
#define MaaMacOSInputMethod_None 0ULL
#define MaaMacOSInputMethod_GlobalEvent 1ULL
#define MaaMacOSInputMethod_PostToPid (1ULL << 1)

// MaaGamepadType:
/**
 * @brief Virtual gamepad type
 *
 * Select ONE type only.
 *
 * | Type          | Description                                    |
 * |---------------|------------------------------------------------|
 * | Xbox360       | Microsoft Xbox 360 Controller (wired)          |
 * | DualShock4    | Sony DualShock 4 Controller (wired)            |
 */
typedef uint64_t MaaGamepadType;
#define MaaGamepadType_Xbox360 0ULL
#define MaaGamepadType_DualShock4 1ULL

// MaaGamepadButton:
/**
 * @brief Virtual gamepad button codes for click_key/key_down/key_up
 *
 * Use these values with MaaControllerPostClickKey, MaaControllerPostKeyDown, MaaControllerPostKeyUp.
 * Values are based on XUSB (Xbox 360) button flags. DS4 face buttons are mapped to Xbox equivalents.
 *
 * Xbox 360 buttons:
 *
 * | Value   | Button              | Description            |
 * |---------|---------------------|------------------------|
 * | 0x1000  | A                   | A button               |
 * | 0x2000  | B                   | B button               |
 * | 0x4000  | X                   | X button               |
 * | 0x8000  | Y                   | Y button               |
 * | 0x0100  | LB (Left Shoulder)  | Left bumper            |
 * | 0x0200  | RB (Right Shoulder) | Right bumper           |
 * | 0x0040  | L_THUMB             | Left stick click       |
 * | 0x0080  | R_THUMB             | Right stick click      |
 * | 0x0010  | START               | Start button           |
 * | 0x0020  | BACK                | Back button            |
 * | 0x0400  | GUIDE               | Guide/Home button      |
 * | 0x0001  | DPAD_UP             | D-pad up               |
 * | 0x0002  | DPAD_DOWN           | D-pad down             |
 * | 0x0004  | DPAD_LEFT           | D-pad left             |
 * | 0x0008  | DPAD_RIGHT          | D-pad right            |
 *
 * DualShock 4 buttons (aliases to Xbox buttons):
 *
 * | Value   | Button    | Xbox Equivalent | Description               |
 * |---------|-----------|-----------------|---------------------------|
 * | 0x1000  | CROSS     | A                   | Cross (X) button          |
 * | 0x2000  | CIRCLE    | B                   | Circle button             |
 * | 0x4000  | SQUARE    | X                   | Square button             |
 * | 0x8000  | TRIANGLE  | Y                   | Triangle button           |
 * | 0x0100  | L1        | LB                  | L1 button                 |
 * | 0x0200  | R1        | RB                  | R1 button                 |
 * | 0x0040  | L3        | L_THUMB             | Left stick click          |
 * | 0x0080  | R3        | R_THUMB             | Right stick click         |
 * | 0x0010  | OPTIONS   | START               | Options button            |
 * | 0x0020  | SHARE     | BACK                | Share button              |
 * | 0x10000 | PS        | -                   | PS button (DS4 special)   |
 * | 0x20000 | TOUCHPAD  | -                   | Touchpad click (DS4 only) |
 */
typedef uint64_t MaaGamepadButton;
// Xbox 360 buttons (XUSB protocol values)
#define MaaGamepadButton_A 0x1000
#define MaaGamepadButton_B 0x2000
#define MaaGamepadButton_X 0x4000
#define MaaGamepadButton_Y 0x8000
#define MaaGamepadButton_LB 0x0100
#define MaaGamepadButton_RB 0x0200
#define MaaGamepadButton_LEFT_THUMB 0x0040
#define MaaGamepadButton_RIGHT_THUMB 0x0080
#define MaaGamepadButton_START 0x0010
#define MaaGamepadButton_BACK 0x0020
#define MaaGamepadButton_GUIDE 0x0400
#define MaaGamepadButton_DPAD_UP 0x0001
#define MaaGamepadButton_DPAD_DOWN 0x0002
#define MaaGamepadButton_DPAD_LEFT 0x0004
#define MaaGamepadButton_DPAD_RIGHT 0x0008

// DualShock 4 face buttons (aliases to Xbox face buttons)
#define MaaGamepadButton_CROSS MaaGamepadButton_A
#define MaaGamepadButton_CIRCLE MaaGamepadButton_B
#define MaaGamepadButton_SQUARE MaaGamepadButton_X
#define MaaGamepadButton_TRIANGLE MaaGamepadButton_Y
#define MaaGamepadButton_L1 MaaGamepadButton_LB
#define MaaGamepadButton_R1 MaaGamepadButton_RB
#define MaaGamepadButton_L3 MaaGamepadButton_LEFT_THUMB
#define MaaGamepadButton_R3 MaaGamepadButton_RIGHT_THUMB
#define MaaGamepadButton_OPTIONS MaaGamepadButton_START
#define MaaGamepadButton_SHARE MaaGamepadButton_BACK

// DualShock 4 special buttons (unique values, no Xbox equivalent)
#define MaaGamepadButton_PS 0x10000
#define MaaGamepadButton_TOUCHPAD 0x20000

// MaaGamepadTouch:
/**
 * @brief Virtual gamepad touch contact definitions for touch_down/touch_move/touch_up
 *
 * For gamepad controller, the touch functions are repurposed for analog inputs:
 * - x, y: Analog stick position
 * - pressure: Trigger value (0~255)
 *
 * Contact mapping:
 *
 * | Contact | Input           | x range     | y range     | pressure   | Description                    |
 * |---------|-----------------|-------------|-------------|------------|--------------------------------|
 * | 0       | Left Stick      | -32768~32767| -32768~32767| ignored    | Left analog stick X/Y position |
 * | 1       | Right Stick     | -32768~32767| -32768~32767| ignored    | Right analog stick X/Y position|
 * | 2       | Left Trigger    | ignored     | ignored     | 0~255      | Left trigger (LT/L2) value     |
 * | 3       | Right Trigger   | ignored     | ignored     | 0~255      | Right trigger (RT/R2) value    |
 *
 * Usage:
 * - touch_down(contact, x, y, pressure): Start analog input
 * - touch_move(contact, x, y, pressure): Update analog input position/value
 * - touch_up(contact): Release/reset analog input to center/zero
 */
typedef uint64_t MaaGamepadTouch;
#define MaaGamepadTouch_LeftStick 0
#define MaaGamepadTouch_RightStick 1
#define MaaGamepadTouch_LeftTrigger 2
#define MaaGamepadTouch_RightTrigger 3

/**
 * Controller feature flags returned by get_features().
 * These flags indicate which input methods the controller supports/prefers.
 */
typedef uint64_t MaaControllerFeature;

/// No special features, controller supports click/swipe/click_key directly.
#define MaaControllerFeature_None 0

/// Controller prefers touch_down/touch_move/touch_up instead of click/swipe.
/// When set, ControllerAgent will use touch_down/touch_up to simulate click,
/// and touch_down/touch_move/touch_up to simulate swipe.
#define MaaControllerFeature_UseMouseDownAndUpInsteadOfClick 1ULL

/// Controller prefers key_down/key_up instead of click_key.
/// When set, ControllerAgent will use key_down + key_up to simulate click_key.
#define MaaControllerFeature_UseKeyboardDownAndUpInsteadOfClick (1ULL << 1)

/// Controller does not scale touch points automatically.
/// When set, ControllerAgent will skip coordinate scaling for touch operations.
#define MaaControllerFeature_NoScalingTouchPoints (1ULL << 2)

typedef struct MaaRect
{
    int32_t x;
    int32_t y;
    int32_t width;
    int32_t height;
} MaaRect;

/*
 * See MaaMsg.h
 */

// Deprecated, use MaaEventCallback instead
typedef void(MAA_CALL* MaaNotificationCallback)(const char* message, const char* details_json, void* notify_trans_arg);

/// void* handle:
/// - MaaTasker* for MaaTasker event
/// - MaaResource* for MaaResource event
/// - MaaController* for MaaController event
/// - MaaContext* for MaaContext event
typedef void(MAA_CALL* MaaEventCallback)(void* handle, const char* message, const char* details_json, void* trans_arg);

typedef MaaBool(MAA_CALL* MaaCustomRecognitionCallback)(
    MaaContext* context,
    MaaTaskId task_id,
    const char* node_name,
    const char* custom_recognition_name,
    const char* custom_recognition_param,
    const MaaImageBuffer* image,
    const MaaRect* roi,
    void* trans_arg,
    /* out */ MaaRect* out_box,
    /* out */ MaaStringBuffer* out_detail);

typedef MaaBool(MAA_CALL* MaaCustomActionCallback)(
    MaaContext* context,
    MaaTaskId task_id,
    const char* node_name,
    const char* custom_action_name,
    const char* custom_action_param,
    MaaRecoId reco_id,
    const MaaRect* box,
    void* trans_arg);
