package com.genymobile.scrcpy.wrappers;

import com.genymobile.scrcpy.Ln;

import android.os.IInterface;
import android.view.InputEvent;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public final class InputManager {

    public static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0;
    public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1;
    public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2;

    private final IInterface manager;
    private Method injectInputEventMethod;

    private static Method setDisplayIdMethod;

    public InputManager(IInterface manager) {
        this.manager = manager;
    }

    private Method getInjectInputEventMethod() throws NoSuchMethodException {
        if (injectInputEventMethod == null) {
            injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class);
        }
        return injectInputEventMethod;
    }

    public boolean injectInputEvent(InputEvent inputEvent, int mode) {
        try {
            Method method = getInjectInputEventMethod();
            return (boolean) method.invoke(manager, inputEvent, mode);
        } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
            Ln.e("Could not invoke method", e);
            return false;
        }
    }

    private static Method getSetDisplayIdMethod() throws NoSuchMethodException {
        if (setDisplayIdMethod == null) {
            setDisplayIdMethod = InputEvent.class.getMethod("setDisplayId", int.class);
        }
        return setDisplayIdMethod;
    }

    public static boolean setDisplayId(InputEvent inputEvent, int displayId) {
        try {
            Method method = getSetDisplayIdMethod();
            method.invoke(inputEvent, displayId);
            return true;
        } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
            Ln.e("Cannot associate a display id to the input event", e);
            return false;
        }
    }
}

@@ -538,24 +538,71 @@
 EventMethod;
+%0A    boolean alternativeInjectInputEventMethod;
 %0A%0A    privat
@@ -839,32 +839,54 @@
 thod == null) %7B%0A
+            try %7B%0A    
             inje
@@ -997,197 +997,667 @@
     
-%7D%0A        return injectInputEventMethod;%0A    %7D%0A%0A    public boolean injectInputEvent(InputEvent inputEvent, int mode) %7B%0A        try %7B%0A            Method method = getInjectInputEventMethod();
+    %7D catch (NoSuchMethodException e) %7B%0A                injectInputEventMethod = manager.getClass().getMethod(%22injectInputEvent%22, InputEvent.class, int.class, int.class);%0A                alternativeInjectInputEventMethod = true;%0A            %7D%0A        %7D%0A        return injectInputEventMethod;%0A    %7D%0A%0A    public boolean injectInputEvent(InputEvent inputEvent, int mode) %7B%0A        try %7B%0A            Method method = getInjectInputEventMethod();%0A            if (alternativeInjectInputEventMethod) %7B%0A                // See %3Chttps://github.com/Genymobile/scrcpy/issues/2250%3E%0A                return (boolean) method.invoke(manager, inputEvent, mode, 0);%0A            %7D
 %0A   

Fix NoSuchMethodException for injectInputEvent()