package com.ttstd.controlled.input;

import android.util.Log;

import com.google.protobuf.InvalidProtocolBufferException;
import com.ttstd.control.Action;
import com.ttstd.control.ControlMessage;

/**
 * 处理控制端发来的输入指令（触摸、按键）。
 * 指令以 protobuf 二进制（{@link ControlMessage}）通过 DataChannel 传输，
 * 解析后委托给 {@link InputExecutor} 接口执行。
 */
public class InputCommandHandler {

    private static final String TAG = "InputCommandHandler";
    private final int screenWidth;
    private final int screenHeight;
    private final InputExecutor inputExecutor;

    /** 控制端请求切换屏幕采集分辨率时的回调（由 ScreenCaptureService 实现）。 */
    public interface ResolutionRequestListener {
        void onResolutionRequested(int width, int height, int fps);
    }

    /** 控制端请求切换屏幕串流模式（WebRTC / 自编码）时的回调。 */
    public interface StreamModeListener {
        void onStreamModeRequested(int mode);
    }

    private ResolutionRequestListener resolutionListener;
    private StreamModeListener streamModeListener;

    public InputCommandHandler(int screenWidth, int screenHeight) {
        this(screenWidth, screenHeight, new SystemInputUtils());
    }

    /**
     * 允许调用方根据权限/环境选择具体的输入执行器。
     *
     * @param screenWidth  真实屏幕宽度（用于坐标映射）
     * @param screenHeight 真实屏幕高度（用于坐标映射）
     * @param inputExecutor 输入执行器（系统注入 / Shell / 无障碍 等）
     */
    public InputCommandHandler(int screenWidth, int screenHeight, InputExecutor inputExecutor) {
        this.screenWidth = screenWidth;
        this.screenHeight = screenHeight;
        this.inputExecutor = inputExecutor;
    }

    public void setResolutionRequestListener(ResolutionRequestListener listener) {
        this.resolutionListener = listener;
    }

    public void setStreamModeListener(StreamModeListener listener) {
        this.streamModeListener = listener;
    }

    public void handleCommand(byte[] data) {
        try {
            ControlMessage command = ControlMessage.parseFrom(data);
            Action action = command.getAction();

            switch (action) {
                case TOUCH:
                    handleTouch(command);
                    break;
                case KEY:
                    handleKey(command);
                    break;
                case SWIPE:
                    handleSwipe(command);
                    break;
                case LONG_PRESS:
                    handleLongPress(command);
                    break;
                case MOTION_EVENT:
                    handleMotionEvent(command);
                    break;
                case SET_RESOLUTION:
                    // 分辨率切换不依赖输入执行器，转发给屏幕采集服务处理。
                    if (resolutionListener != null) {
                        resolutionListener.onResolutionRequested(
                                command.getWidth(), command.getHeight(), command.getFps());
                    } else {
                        Log.w(TAG, "SET_RESOLUTION received but no listener registered");
                    }
                    break;
                case SET_STREAM_MODE:
                    // 串流模式切换不依赖输入执行器，转发给屏幕采集服务处理。
                    if (streamModeListener != null) {
                        streamModeListener.onStreamModeRequested(command.getStreamMode());
                    } else {
                        Log.w(TAG, "SET_STREAM_MODE received but no listener registered");
                    }
                    break;
                default:
                    Log.w(TAG, "Unknown action: " + action);
            }
        } catch (InvalidProtocolBufferException e) {
            Log.e(TAG, "Error parsing command: " + e.getMessage(), e);
        }
    }

    /**
     * 释放持有的资源。
     */
    public void release() {
        if (inputExecutor != null) {
            inputExecutor.release();
        }
    }

    private void handleMotionEvent(ControlMessage command) {
        int action = command.getMotionAction();
        float relX = (float) command.getX();
        float relY = (float) command.getY();
        int x = (int) (relX * screenWidth);
        int y = (int) (relY * screenHeight);
        Log.d(TAG, "Motion event: " + action + " at: " + x + ", " + y);
        inputExecutor.injectMotionEvent(action, x, y);
    }

    private void handleTouch(ControlMessage command) {
        float relX = (float) command.getX();
        float relY = (float) command.getY();
        int x = (int) (relX * screenWidth);
        int y = (int) (relY * screenHeight);

        Log.d(TAG, "Touch at: " + x + ", " + y);
        inputExecutor.injectTap(x, y);
    }

    private void handleKey(ControlMessage command) {
        int keyCode = command.getKeyCode();
        Log.d(TAG, "Key press: " + keyCode);
        inputExecutor.injectKeyEvent(keyCode);
    }

    private void handleSwipe(ControlMessage command) {
        float relX1 = (float) command.getX1();
        float relY1 = (float) command.getY1();
        float relX2 = (float) command.getX2();
        float relY2 = (float) command.getY2();
        long duration = command.getDuration();

        int x1 = (int) (relX1 * screenWidth);
        int y1 = (int) (relY1 * screenHeight);
        int x2 = (int) (relX2 * screenWidth);
        int y2 = (int) (relY2 * screenHeight);

        Log.d(TAG, "Swipe from (" + x1 + "," + y1 + ") to (" + x2 + "," + y2 + ")");
        inputExecutor.injectSwipe(x1, y1, x2, y2, duration);
    }

    private void handleLongPress(ControlMessage command) {
        float relX = (float) command.getX();
        float relY = (float) command.getY();
        int x = (int) (relX * screenWidth);
        int y = (int) (relY * screenHeight);

        Log.d(TAG, "Long press at: " + x + ", " + y);
        inputExecutor.injectLongPress(x, y);
    }
}
