package com.ttstd.controlled.input;

import android.util.Log;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Locale;

/**
 * 通过 Root Shell (su) 执行注入操作的实现类。
 * 解决普通 Shell 无法获取足够权限执行 input 命令的问题。
 */
public class RootShellInputUtils implements InputExecutor {
    private static final String TAG = "RootShellInputUtils";
    
    private Process mSuProcess;
    private DataOutputStream mSuStream;

    @Override
    public void injectTap(int x, int y) {
        executeRootCommand(String.format(Locale.US, "input tap %d %d", x, y));
    }

    @Override
    public void injectLongPress(int x, int y) {
        injectSwipe(x, y, x, y, 1000);
    }

    @Override
    public void injectSwipe(int x1, int y1, int x2, int y2, long duration) {
        executeRootCommand(String.format(Locale.US, "input swipe %d %d %d %d %d", x1, y1, x2, y2, duration));
    }

    @Override
    public void injectKeyEvent(int keyCode) {
        executeRootCommand(String.format(Locale.US, "input keyevent %d", keyCode));
    }

    @Override
    public void injectMotionEvent(int action, int x, int y) {
        // Root Shell 下执行 input 命令开销较大
        if (action == 0) { // ACTION_DOWN
            injectTap(x, y);
        }
    }

    /**
     * 执行需要 root 权限的命令。
     * 使用持久的 su 进程以减少重复创建进程的开销。
     */
    private synchronized void executeRootCommand(String command) {
        try {
            if (mSuProcess == null || mSuStream == null) {
                mSuProcess = Runtime.getRuntime().exec("su");
                mSuStream = new DataOutputStream(mSuProcess.getOutputStream());
            }
            Log.d(TAG, "Executing root command: " + command);
            mSuStream.writeBytes(command + "\n");
            mSuStream.flush();
        } catch (Exception e) {
            Log.e(TAG, "Error executing root command: " + command, e);
            closeSuProcess();
        }
    }

    @Override
    public void release() {
        closeSuProcess();
    }

    private synchronized void closeSuProcess() {
        try {
            if (mSuStream != null) {
                mSuStream.writeBytes("exit\n");
                mSuStream.flush();
                mSuStream.close();
            }
            if (mSuProcess != null) {
                mSuProcess.destroy();
            }
        } catch (IOException ignored) {
        } finally {
            mSuStream = null;
            mSuProcess = null;
        }
    }

    @Override
    protected void finalize() throws Throwable {
        closeSuProcess();
        super.finalize();
    }
}

