package org.tzd.frida.windows;

/**
 * @author tzdwindows 7
 */
public class Frida {
    private final String jsCode;
    private FridaThread thread;
    boolean isRunning;
    long pid;

    /**
     * 构造一个新的 <code>Frida</code> 实例。
     *
     * @param jsCode 需要注入的 JavaScript 代码。
     * @param pid 目标进程的进程ID。
     *
     * <p>此构造函数用于初始化一个新的 <code>Frida</code> 对象，指定要注入的 JavaScript 代码及目标进程ID。</p>
     */
    public Frida(String jsCode, long pid) {
        this.jsCode = jsCode;
        this.pid = pid;
        isRunning = false;
    }

    /**
     * 启动并返回一个新的线程，用于执行JavaScript注入。
     *
     * @return 返回一个线程管理类 <code>FridaThread</code>，方便对线程进行统一管理。
     *
     * <p>该方法的工作流程如下：</p>
     * <ol>
     *     <li<code>new FridaThread(() -> { ... })</code>: 创建一个新的线程，该线程执行 JavaScript 注入操作。线程内部会设置 <code>isRunning = true</code> 并调用 <code>Frida0.injection(jsCode, this)</code> 来注入 JavaScript 代码。</li>
     * </ol>
     *
     * <p>示例用法：</p>
     * <pre>
     * FridaThread thread = frida.run();
     * thread.setStart(true)
     * thread.start();  // 启动线程
     * </pre>
     */
    public FridaThread run() {
        thread = new FridaThread(() -> {
            isRunning = true;
            Frida0.injection(jsCode,this);
        },this);
        return thread;
    }

    /**
     * 启动并返回一个新的线程，用于执行JavaScript注入。
     *
     * @param callback 在循环中的回调函数
     * @return 一个线程管理类，方便对线程进行统一管理
     *
     * <p>该方法的工作流程如下：</p>
     * <ol>
     *     <li><code>run(Runnable... callback)</code>: 首先创建一个新的 <code>FridaThread</code>，并传入一个 <code>Runnable</code> 任务，任务会在新线程中执行。任务内会调用 <code>Frida0.injection(jsCode, this, callback)</code>，注入并执行 JavaScript 代码。</li>
     *     <li><code>execute(FridaRunnable runnable)</code>: <code>execute</code> 方法允许你定义在 <code>FridaThread</code> 中执行的额外任务。<code>FridaRunnable</code> 接口的 <code>run</code> 方法会被调用，允许你与 <code>Frida</code> 对象交互，添加回调消息或其他操作。</li>
     *     <li><code>start()</code>: 启动线程，执行上述所有任务。</li>
     * </ol>
     *
     * <p>示例用法：</p>
     * <pre>
     * frida.run(new Runnable() {
     *     @Override
     *     public void run() {
     *         // 在此处添加需要执行的代码
     *     }
     * }).execute(new FridaRunnable() {
     *     @Override
     *     public void run(Frida frida) {
     *         // 注册回调消息，接收信息
     *         frida.addCallbackMessage(new CallbackMessage() {
     *             @Override
     *             public void onMessage(String message) {
     *                 System.out.println(message); // 打印收到的消息
     *             }
     *         });
     *     }
     * }).start(); // 启动线程
     * </pre>
     *
     * <p>在这个示例中，<code>run()</code> 方法首先创建并配置一个新的线程，<code>execute()</code> 方法为线程添加了一个回调函数，接收到消息时会触发该回调函数。最后，调用 <code>start()</code> 启动线程的执行。</p>
     * <p>当然你如果非要在FridaThread中直接使用start，而不经过execute的话我们会抛出异常 throw new RuntimeException("Basic information is not configured"); </p>
     */
    public FridaThread run(Runnable... callback) {
        thread = new FridaThread(() -> {
            isRunning = true;
            Frida0.injection(jsCode, this, callback);
        }, this);
        return thread;
    }

    /**
     * 将回调消息添加到消息列表中。
     *
     * @param callbackMessage 要添加的回调消息对象。
     *
     * <p>此方法会将传入的 <code>callbackMessage</code> 对象添加到 <code>Frida0.CALLBACK_MESSAGE_LIST</code> 中。</p>
     */
    public void addCallbackMessage(CallbackMessage callbackMessage) {
        Frida0.CALLBACK_MESSAGE_LIST.add(callbackMessage);
    }

    /**
     * 从消息列表中移除指定的回调消息。
     *
     * @param callbackMessage 要移除的回调消息对象。
     *
     * <p>此方法会将传入的 <code>callbackMessage</code> 对象从 <code>Frida0.CALLBACK_MESSAGE_LIST</code> 中移除。</p>
     */
    public void clearCallbackMessage(CallbackMessage callbackMessage) {
        Frida0.CALLBACK_MESSAGE_LIST.remove(callbackMessage);
    }

    /**
     * 清空所有回调消息。
     *
     * <p>此方法会清空 <code>Frida0.CALLBACK_MESSAGE_LIST</code> 中的所有回调消息。</p>
     */
    public void clearCallbackMessage() {
        Frida0.CALLBACK_MESSAGE_LIST.clear();
    }
}
