package com.ttstd.controlled.input;

import android.accessibilityservice.GestureDescription;
import android.graphics.Path;
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;

import com.ttstd.controlled.accessibility.KeyboardAccessibilityService;

/**
 * 基于无障碍服务（AccessibilityService）的输入执行器。
 * <p>
 * 适用于没有系统签名、也没有 root 权限的普通应用：
 * - 触摸 / 滑动 / 长按 / 连续手势：通过 AccessibilityService.dispatchGesture 模拟；
 * - 按键：通过 KeyboardAccessibilityService.pressKey 模拟系统级全局按键。
 * <p>
 * 注意：无障碍无法模拟任意字符按键，仅支持返回 / 主页 / 多任务 / 通知 / 音量等全局动作。
 */
public class AccessibilityInputUtils implements InputExecutor {

    private static final String TAG = "AccessibilityInputUtils";

    // 连续手势（MOTION_EVENT）的累积路径
    private Path motionPath;
    private long motionStartTime;

    private KeyboardAccessibilityService getService() {
        return KeyboardAccessibilityService.getInstance();
    }

    @Override
    public void injectTap(int x, int y) {
        Path path = new Path();
        path.moveTo(x, y);
        // 同一点、短时长即模拟“按下-抬起”的点击
        dispatch(path, 1, 50);
    }

    @Override
    public void injectLongPress(int x, int y) {
        Path path = new Path();
        path.moveTo(x, y);
        dispatch(path, 1, 1000);
    }

    @Override
    public void injectSwipe(int x1, int y1, int x2, int y2, long duration) {
        Path path = new Path();
        path.moveTo(x1, y1);
        path.lineTo(x2, y2);
        dispatch(path, 0, Math.max(50, duration));
    }

    @Override
    public void injectKeyEvent(int keyCode) {
        KeyboardAccessibilityService svc = getService();
        if (svc == null) {
            Log.w(TAG, "Accessibility service not running, cannot inject key");
            return;
        }
        boolean handled = svc.pressKey(keyCode);
        if (!handled) {
            Log.w(TAG, "Key code " + keyCode + " is not supported via accessibility");
        }
    }

    @Override
    public void injectMotionEvent(int action, int x, int y) {
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                motionPath = new Path();
                motionPath.moveTo(x, y);
                motionStartTime = SystemClock.uptimeMillis();
                break;
            case MotionEvent.ACTION_MOVE:
                if (motionPath != null) {
                    motionPath.lineTo(x, y);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (motionPath != null) {
                    long duration = Math.max(1, SystemClock.uptimeMillis() - motionStartTime);
                    dispatch(motionPath, 0, duration);
                    motionPath = null;
                }
                break;
            default:
                Log.w(TAG, "Unknown motion action: " + action);
        }
    }

    private void dispatch(Path path, long startOffset, long duration) {
        KeyboardAccessibilityService svc = getService();
        if (svc == null) {
            Log.w(TAG, "Accessibility service not running, cannot dispatch gesture");
            return;
        }
        GestureDescription.Builder builder = new GestureDescription.Builder();
        builder.addStroke(new GestureDescription.StrokeDescription(path, startOffset, duration));
        boolean result = svc.dispatchGesture(builder.build(), null, null);
        if (!result) {
            Log.w(TAG, "dispatchGesture failed");
        }
    }
}
