import time
from typing import Union

from maa_mcp.core import mcp, object_registry, controller_info_registry, ControllerType


@mcp.tool(
    name="click",
    description="""
    在设备屏幕上执行单点点击操作，支持长按。

    参数：
    - controller_id: 控制器 ID，由 connect_adb_device() 或 connect_window() 返回
    - x: 目标点的 X 坐标（像素，整数）
    - y: 目标点的 Y 坐标（像素，整数）
    - button: 按键编号，默认为 0
      - ADB 控制器：手指编号（0 为第一根手指）
      - Win32 控制器：鼠标按键（0=左键, 1=右键, 2=中键）
    - duration: 按下持续时间（毫秒），默认为 50；设置较大值可实现长按

    返回值：
    - 成功：返回 True
    - 失败：返回 False

    说明：
    坐标系统以屏幕左上角为原点 (0, 0)，X 轴向右，Y 轴向下。
""",
)
def click(
    controller_id: str, x: int, y: int, button: int = 0, duration: int = 50
) -> bool:
    controller = object_registry.get(controller_id)
    if not controller:
        return False
    if not controller.post_touch_down(x, y, contact=button).wait().succeeded:
        return False
    time.sleep(duration / 1000.0)
    return controller.post_touch_up(contact=button).wait().succeeded


@mcp.tool(
    name="double_click",
    description="""
    在设备屏幕上执行双击操作。

    参数：
    - controller_id: 控制器 ID，由 connect_adb_device() 或 connect_window() 返回
    - x: 目标点的 X 坐标（像素，整数）
    - y: 目标点的 Y 坐标（像素，整数）
    - button: 按键编号，默认为 0
      - ADB 控制器：手指编号（0 为第一根手指）
      - Win32 控制器：鼠标按键（0=左键, 1=右键, 2=中键）
    - duration: 每次按下的持续时间（毫秒），默认为 50
    - interval: 两次点击之间的间隔时间（毫秒），默认为 100

    返回值：
    - 成功：返回 True
    - 失败：返回 False

    说明：
    坐标系统以屏幕左上角为原点 (0, 0)，X 轴向右，Y 轴向下。
""",
)
def double_click(
    controller_id: str,
    x: int,
    y: int,
    button: int = 0,
    duration: int = 50,
    interval: int = 100,
) -> bool:
    controller = object_registry.get(controller_id)
    if not controller:
        return False
    # 第一次点击
    if not controller.post_touch_down(x, y, contact=button).wait().succeeded:
        return False
    time.sleep(duration / 1000.0)
    if not controller.post_touch_up(contact=button).wait().succeeded:
        return False
    # 间隔等待
    time.sleep(interval / 1000.0)
    # 第二次点击
    if not controller.post_touch_down(x, y, contact=button).wait().succeeded:
        return False
    time.sleep(duration / 1000.0)
    return controller.post_touch_up(contact=button).wait().succeeded


@mcp.tool(
    name="swipe",
    description="""
    在设备屏幕上执行手势滑动操作，模拟手指从起始点滑动到终点。

    使用建议：
    - ADB（Android 设备/模拟器）场景下，如需滚动/翻页，优先使用 swipe()
    - Windows（桌面窗口）场景下，如需滚动列表/页面，优先使用 scroll()；仅在需要拖拽/滑动手势时使用 swipe()

    参数：
    - controller_id: 控制器 ID，由 connect_adb_device() 或 connect_window() 返回
    - start_x: 起始点的 X 坐标（像素，整数）
    - start_y: 起始点的 Y 坐标（像素，整数）
    - end_x: 终点的 X 坐标（像素，整数）
    - end_y: 终点的 Y 坐标（像素，整数）
    - duration: 滑动持续时间（毫秒，整数）

    返回值：
    - 成功：返回 True
    - 失败：返回 False

    说明：
    坐标系统以屏幕左上角为原点 (0, 0)。duration 参数控制滑动速度，数值越大滑动越慢。
""",
)
def swipe(
    controller_id: str,
    start_x: int,
    start_y: int,
    end_x: int,
    end_y: int,
    duration: int,
) -> bool:
    controller = object_registry.get(controller_id)
    if not controller:
        return False
    return (
        controller.post_swipe(start_x, start_y, end_x, end_y, duration).wait().succeeded
    )


@mcp.tool(
    name="input_text",
    description="""
    在设备屏幕上执行输入文本操作。

    参数：
    - controller_id: 控制器 ID，由 connect_adb_device() 或 connect_window() 返回
    - text: 要输入的文本（字符串）

    返回值：
    - 成功：返回 True
    - 失败：返回 False

    说明：
    输入文本操作将模拟用户在设备屏幕上输入文本，支持中文、英文等常见字符。
    """,
)
def input_text(controller_id: str, text: str) -> bool:
    controller = object_registry.get(controller_id)
    if not controller:
        return False
    return controller.post_input_text(text).wait().succeeded


@mcp.tool(
    name="click_key",
    description="""
    在设备屏幕上执行按键点击操作，支持长按。

    参数：
    - controller_id: 控制器 ID，由 connect_adb_device() 或 connect_window() 返回
    - key: 要点击的按键（虚拟按键码）
    - duration: 按键持续时间（毫秒），默认为 50；设置较大值可实现长按

    返回值：
    - 成功：返回 True
    - 失败：返回 False

    常用按键值：
    ADB 控制器（Android KeyEvent）：
      - 返回键: 4
      - Home键: 3
      - 菜单键: 82
      - 回车/确认: 66
      - 删除/退格: 67
      - 音量+: 24
      - 音量-: 25
      - 电源键: 26

    Win32 控制器（Windows Virtual-Key Codes）：
      - 回车: 13 (0x0D)
      - ESC: 27 (0x1B)
      - 退格: 8 (0x08)
      - Tab: 9 (0x09)
      - 空格: 32 (0x20)
      - 左箭头: 37 (0x25)
      - 上箭头: 38 (0x26)
      - 右箭头: 39 (0x27)
      - 下箭头: 40 (0x28)
    """,
)
def click_key(controller_id: str, key: int, duration: int = 50) -> bool:
    controller = object_registry.get(controller_id)
    if not controller:
        return False
    if not controller.post_key_down(key).wait().succeeded:
        return False
    time.sleep(duration / 1000.0)
    return controller.post_key_up(key).wait().succeeded


@mcp.tool(name="keyboard_shortcut", description="""
    在设备屏幕上执行键盘快捷键操作。

    参数：
    - controller_id: 控制器 ID，由 connect_adb_device() 或 connect_window() 返回
    - modifiers: 修饰键列表（虚拟按键码），支持多个修饰键
    - primary_key: 主键（虚拟按键码）
    - duration: 按键持续时间（毫秒），默认为 50；设置较大值可实现长按

    返回值：
    - 成功：返回 True
    - 失败：返回 False

    常用按键值：
    修饰键（Windows Virtual-Key Codes）：
      - Left Shift: 160 (0xA0)
      - Left Ctrl: 162 (0xA2)
      - Left Alt: 164 (0xA4)
      - Left Windows: 91 (0x5B)

    注意：该方法仅对 Windows 窗口控制器，且在 Seize 控制方式下有效，其他控制方式不支持。
""")
def keyboard_shortcut(
    controller_id: str, modifiers: list[int], primary_key: int, duration: int = 50
) -> Union[bool, str]:
    controller = object_registry.get(controller_id)
    if not controller:
        return False

    # 检查控制器类型和配置
    info = controller_info_registry.get(controller_id)
    if info:
        if info.controller_type == ControllerType.ADB:
            return "keyboard_shortcut 不支持 ADB 控制器，该方法仅适用于 Windows 窗口控制器。请使用 click_key 进行单个按键操作。"
        if info.controller_type == ControllerType.WIN32 and info.keyboard_method != "Seize":
            return f"keyboard_shortcut 仅支持 Seize 键盘模式，当前为 {info.keyboard_method}。可对同一窗口调用 connect_window(keyboard_method='Seize') 获取新 controller_id，原 controller_id 仍可用于其他操作。"

    for modifier in modifiers:
        if not controller.post_key_down(modifier).wait().succeeded:
            return False

    if not controller.post_key_down(primary_key).wait().succeeded:
        return False
    time.sleep(duration / 1000.0)
    if not controller.post_key_up(primary_key).wait().succeeded:
        return False

    for modifier in modifiers:
        if not controller.post_key_up(modifier).wait().succeeded:
            return False
    return True


@mcp.tool(
    name="scroll",
    description="""
    在设备屏幕上执行鼠标滚轮操作。

    使用建议：
    - Windows（桌面窗口）场景下，如需滚动列表/页面，优先使用 scroll()
    - ADB（Android 设备/模拟器）不支持 scroll()，请使用 swipe() 进行滑动/滚动

    参数：
    - controller_id: 控制器 ID，由 connect_adb_device() 或 connect_window() 返回
    - x: 滚动的 X 坐标（像素，建议传入 120 的整数倍以获得最佳兼容性）
    - y: 滚动的 Y 坐标（像素，建议传入 120 的整数倍以获得最佳兼容性）

    返回值：
    - 成功：返回 True
    - 失败：返回 False

    注意：该方法仅对 Windows 窗口控制有效，无法作用于 ADB。
    """,
)
def scroll(controller_id: str, x: int, y: int) -> Union[bool, str]:
    controller = object_registry.get(controller_id)
    if not controller:
        return False

    # 检查控制器类型
    info = controller_info_registry.get(controller_id)
    if info and info.controller_type == ControllerType.ADB:
        return "scroll 不支持 ADB 控制器，该方法仅适用于 Windows 窗口控制器。请使用 swipe 进行滑动操作。"

    return controller.post_scroll(x, y).wait().succeeded
