// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chromoting;

import android.graphics.PointF;
import android.view.KeyEvent;
import android.view.MotionEvent;

import org.chromium.chromoting.jni.TouchEventData;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * A set of functions to send users' activities, which are represented by Android classes, to
 * remote host machine. This class uses a {@link InputStub} to do the real injections.
 */
public final class InputEventSender {
    private static final int[] CTRL_ALT_DEL = {
            KeyEvent.KEYCODE_CTRL_LEFT, KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.KEYCODE_FORWARD_DEL,
    };

    private final InputStub mInjector;

    /** Set of pressed keys for which we've sent TextEvent. */
    private final Set<Integer> mPressedTextKeys;

    public InputEventSender(InputStub injector) {
        Preconditions.notNull(injector);
        mInjector = injector;
        mPressedTextKeys = new TreeSet<>();
    }

    public void sendMouseEvent(PointF pos, int button, boolean down) {
        Preconditions.isTrue(button == InputStub.BUTTON_UNDEFINED
                || button == InputStub.BUTTON_LEFT
                || button == InputStub.BUTTON_MIDDLE
                || button == InputStub.BUTTON_RIGHT);
        mInjector.sendMouseEvent((int) pos.x, (int) pos.y, button, down);
    }

    public void sendMouseDown(PointF pos, int button) {
        sendMouseEvent(pos, button, true);
    }

    public void sendMouseUp(PointF pos, int button) {
        sendMouseEvent(pos, button, false);
    }

    public void sendMouseClick(PointF pos, int button) {
        sendMouseDown(pos, button);
        sendMouseUp(pos, button);
    }

    public void sendCursorMove(PointF pos) {
        sendMouseUp(pos, InputStub.BUTTON_UNDEFINED);
    }

    // TODO(zijiehe): This function will be eventually removed after {@link InputStrategyInterface}
    // has been deprecated.
    public void sendCursorMove(float x, float y) {
        sendCursorMove(new PointF(x, y));
    }

    public void sendMouseWheelEvent(float distanceX, float distanceY) {
        mInjector.sendMouseWheelEvent((int) distanceX, (int) distanceY);
    }

    public void sendReverseMouseWheelEvent(float distanceX, float distanceY) {
        sendMouseWheelEvent(-distanceX, -distanceY);
    }

    /**
     * Extracts the touch point data from a MotionEvent, converts each point into a marshallable
     * object and passes the set of points to the JNI layer to be transmitted to the remote host.
     *
     * @param event The event to send to the remote host for injection.  NOTE: This object must be
     *              updated to represent the remote machine's coordinate system before calling this
     *              function.
     */
    public void sendTouchEvent(MotionEvent event) {
        int action = event.getActionMasked();
        TouchEventData.EventType touchEventType = TouchEventData.EventType.fromMaskedAction(action);
        List<TouchEventData> touchEventList = new ArrayList<TouchEventData>();

        if (action == MotionEvent.ACTION_MOVE) {
            // In order to process all of the events associated with an ACTION_MOVE event, we need
            // to walk the list of historical events in order and add each event to our list, then
            // retrieve the current move event data.
            int pointerCount = event.getPointerCount();
            int historySize = event.getHistorySize();
            for (int h = 0; h < historySize; ++h) {
                for (int p = 0; p < pointerCount; ++p) {
                    touchEventList.add(new TouchEventData(event.getPointerId(p),
                            event.getHistoricalX(p, h), event.getHistoricalY(p, h),
                            event.getHistoricalSize(p, h), event.getHistoricalSize(p, h),
                            event.getHistoricalOrientation(p, h),
                            event.getHistoricalPressure(p, h)));
                }
            }

            for (int p = 0; p < pointerCount; p++) {
                touchEventList.add(new TouchEventData(event.getPointerId(p), event.getX(p),
                        event.getY(p), event.getSize(p), event.getSize(p), event.getOrientation(p),
                        event.getPressure(p)));
            }
        } else {
            // For all other events, we only want to grab the current/active pointer.  The event
            // contains a list of every active pointer but passing all of of these to the host can
            // cause confusion on the remote OS side and result in broken touch gestures.
            int activePointerIndex = event.getActionIndex();
            touchEventList.add(new TouchEventData(event.getPointerId(activePointerIndex),
                    event.getX(activePointerIndex), event.getY(activePointerIndex),
                    event.getSize(activePointerIndex), event.getSize(activePointerIndex),
                    event.getOrientation(activePointerIndex),
                    event.getPressure(activePointerIndex)));
        }

        if (!touchEventList.isEmpty()) {
            mInjector.sendTouchEvent(touchEventType, touchEventList.toArray(new TouchEventData[0]));
        }
    }

    /**
     * Converts the {@link KeyEvent} into low-level events and sends them to the host as either
     * key-events or text-events. This contains some logic for handling some special keys, and
     * avoids sending a key-up event for a key that was previously injected as a text-event.
     */
    public boolean sendKeyEvent(KeyEvent event) {
        int keyCode = event.getKeyCode();
        boolean pressed = event.getAction() == KeyEvent.ACTION_DOWN;

        // Events received from software keyboards generate TextEvent in two
        // cases:
        //   1. This is an ACTION_MULTIPLE event.
        //   2. Ctrl, Alt and Meta are not pressed.
        // This ensures that on-screen keyboard always injects input that
        // correspond to what user sees on the screen, while physical keyboard
        // acts as if it is connected to the remote host.
        if (event.getAction() == KeyEvent.ACTION_MULTIPLE) {
            mInjector.sendTextEvent(event.getCharacters());
            return true;
        }

        // For Enter getUnicodeChar() returns 10 (line feed), but we still
        // want to send it as KeyEvent.
        int unicode = keyCode != KeyEvent.KEYCODE_ENTER ? event.getUnicodeChar() : 0;

        boolean no_modifiers =
                !event.isAltPressed() && !event.isCtrlPressed() && !event.isMetaPressed();

        if (pressed && unicode != 0 && no_modifiers) {
            mPressedTextKeys.add(keyCode);
            int[] codePoints = {unicode};
            mInjector.sendTextEvent(new String(codePoints, 0, 1));
            return true;
        }

        if (!pressed && mPressedTextKeys.contains(keyCode)) {
            mPressedTextKeys.remove(keyCode);
            return true;
        }

        switch (keyCode) {
            // KEYCODE_AT, KEYCODE_POUND, KEYCODE_STAR and KEYCODE_PLUS are
            // deprecated, but they still need to be here for older devices and
            // third-party keyboards that may still generate these events. See
            // https://source.android.com/devices/input/keyboard-devices.html#legacy-unsupported-keys
            case KeyEvent.KEYCODE_AT:
                mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, pressed);
                mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_2, pressed);
                return true;

            case KeyEvent.KEYCODE_POUND:
                mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, pressed);
                mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_3, pressed);
                return true;

            case KeyEvent.KEYCODE_STAR:
                mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, pressed);
                mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_8, pressed);
                return true;

            case KeyEvent.KEYCODE_PLUS:
                mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, pressed);
                mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_EQUALS, pressed);
                return true;

            default:
                // We try to send all other key codes to the host directly.
                return mInjector.sendKeyEvent(0, keyCode, pressed);
        }
    }

    public void sendKeyDown(int keyCode) {
        mInjector.sendKeyEvent(0, keyCode, true);
    }

    public void sendKeyUp(int keyCode) {
        mInjector.sendKeyEvent(0, keyCode, false);
    }

    /**
     * Sends key combinations such as Ctrl-Alt-Del. This injects a key-down event for every key in
     * the list, and then injects the corresponding key-up events. If null or an empty |keyCodes|
     * is passed, nothing will be injected.
     */
    public void sendKeysPress(int[] keyCodes) {
        if (keyCodes != null && keyCodes.length > 0) {
            for (int keyCode : keyCodes) {
                sendKeyDown(keyCode);
            }
            for (int keyCode : keyCodes) {
                sendKeyUp(keyCode);
            }
        }
    }

    public void sendCtrlAltDel() {
        sendKeysPress(CTRL_ALT_DEL);
    }
}
