// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/android/shared/input_events_generator.h"

#include <android/input.h>
#include <android/keycodes.h>
#include <jni.h>
#include <math.h>
#include <utility>

#include "starboard/android/shared/application_android.h"
#include "starboard/android/shared/jni_env_ext.h"
#include "starboard/android/shared/jni_utils.h"
#include "starboard/key.h"

namespace starboard {
namespace android {
namespace shared {

using ::starboard::shared::starboard::Application;
typedef ::starboard::android::shared::InputEventsGenerator::Event Event;
typedef ::starboard::android::shared::InputEventsGenerator::Events Events;

namespace {

SbKeyLocation AInputEventToSbKeyLocation(AInputEvent* event) {
  int32_t keycode = AKeyEvent_getKeyCode(event);
  switch (keycode) {
    case AKEYCODE_ALT_LEFT:
    case AKEYCODE_CTRL_LEFT:
    case AKEYCODE_META_LEFT:
    case AKEYCODE_SHIFT_LEFT:
      return kSbKeyLocationLeft;
    case AKEYCODE_ALT_RIGHT:
    case AKEYCODE_CTRL_RIGHT:
    case AKEYCODE_META_RIGHT:
    case AKEYCODE_SHIFT_RIGHT:
      return kSbKeyLocationRight;
  }
  return kSbKeyLocationUnspecified;
}

unsigned int AInputEventToSbModifiers(AInputEvent* event) {
  int32_t meta = AKeyEvent_getMetaState(event);
  unsigned int modifiers = kSbKeyModifiersNone;
  if (meta & AMETA_ALT_ON) {
    modifiers |= kSbKeyModifiersAlt;
  }
  if (meta & AMETA_CTRL_ON) {
    modifiers |= kSbKeyModifiersCtrl;
  }
  if (meta & AMETA_META_ON) {
    modifiers |= kSbKeyModifiersMeta;
  }
  if (meta & AMETA_SHIFT_ON) {
    modifiers |= kSbKeyModifiersShift;
  }
  return modifiers;
}

std::unique_ptr<Event> CreateMoveEventWithKey(
    int32_t device_id,
    SbWindow window,
    SbKey key,
    SbKeyLocation location,
    const SbInputVector& input_vector) {
  std::unique_ptr<SbInputData> data(new SbInputData());
  memset(data.get(), 0, sizeof(*data));

  // window
  data->window = window;
  data->type = kSbInputEventTypeMove;
  data->device_type = kSbInputDeviceTypeGamepad;
  data->device_id = device_id;

  // key
  data->key = key;
  data->key_location = location;
  data->key_modifiers = kSbKeyModifiersNone;
  data->position = input_vector;

  return std::unique_ptr<Event>(
      new Application::Event(kSbEventTypeInput, data.release(),
                             &Application::DeleteDestructor<SbInputData>));
}

float GetFlat(jobject input_device, int axis) {
  JniEnvExt* env = JniEnvExt::Get();
  ScopedLocalJavaRef<jobject> motion_range(env->CallObjectMethodOrAbort(
      input_device, "getMotionRange",
      "(I)Landroid/view/InputDevice$MotionRange;", axis));

  float flat =
      env->CallFloatMethodOrAbort(motion_range.Get(), "getFlat", "()F");

  SB_DCHECK(flat < 1.0f);
  return flat;
}

bool IsDPadKey(SbKey key) {
  return key == kSbKeyGamepadDPadUp || key == kSbKeyGamepadDPadDown ||
         key == kSbKeyGamepadDPadLeft || key == kSbKeyGamepadDPadRight;
}

SbKey AInputEventToSbKey(AInputEvent* event) {
  int32_t keycode = AKeyEvent_getKeyCode(event);
  switch (keycode) {
    // Modifiers
    case AKEYCODE_ALT_LEFT:
    case AKEYCODE_ALT_RIGHT:
    case AKEYCODE_MENU:
      return kSbKeyMenu;
    case AKEYCODE_CTRL_LEFT:
    case AKEYCODE_CTRL_RIGHT:
      return kSbKeyControl;
    case AKEYCODE_META_LEFT:
      return kSbKeyLwin;
    case AKEYCODE_META_RIGHT:
      return kSbKeyRwin;
    case AKEYCODE_SHIFT_LEFT:
    case AKEYCODE_SHIFT_RIGHT:
      return kSbKeyShift;
    case AKEYCODE_CAPS_LOCK:
      return kSbKeyCapital;
    case AKEYCODE_NUM_LOCK:
      return kSbKeyNumlock;
    case AKEYCODE_SCROLL_LOCK:
      return kSbKeyScroll;

    // System functions
    case AKEYCODE_SLEEP:
      return kSbKeySleep;
    case AKEYCODE_HELP:
      return kSbKeyHelp;

    // Navigation
    case AKEYCODE_BACK:  // Android back button, not backspace
    case AKEYCODE_ESCAPE:
      return kSbKeyEscape;

    // Enter/Select
    case AKEYCODE_ENTER:
    case AKEYCODE_NUMPAD_ENTER:
      return kSbKeyReturn;

    // Focus movement
    case AKEYCODE_PAGE_UP:
      return kSbKeyPrior;
    case AKEYCODE_PAGE_DOWN:
      return kSbKeyNext;
    case AKEYCODE_MOVE_HOME:
      return kSbKeyHome;
    case AKEYCODE_MOVE_END:
      return kSbKeyEnd;

    // D-pad
    case AKEYCODE_DPAD_UP:
      return kSbKeyGamepadDPadUp;
    case AKEYCODE_DPAD_DOWN:
      return kSbKeyGamepadDPadDown;
    case AKEYCODE_DPAD_LEFT:
      return kSbKeyGamepadDPadLeft;
    case AKEYCODE_DPAD_RIGHT:
      return kSbKeyGamepadDPadRight;
    case AKEYCODE_DPAD_CENTER:
      return kSbKeyGamepad1;

    // Game controller
    case AKEYCODE_BUTTON_A:
      return kSbKeyGamepad1;
    case AKEYCODE_BUTTON_B:
      return kSbKeyGamepad2;
    case AKEYCODE_BUTTON_C:
      return kSbKeyUnknown;
    case AKEYCODE_BUTTON_X:
      return kSbKeyGamepad3;
    case AKEYCODE_BUTTON_Y:
      return kSbKeyGamepad4;
    case AKEYCODE_BUTTON_L1:
      return kSbKeyGamepadLeftBumper;
    case AKEYCODE_BUTTON_R1:
      return kSbKeyGamepadRightBumper;
    case AKEYCODE_BUTTON_L2:
      return kSbKeyGamepadLeftTrigger;
    case AKEYCODE_BUTTON_R2:
      return kSbKeyGamepadRightTrigger;
    case AKEYCODE_BUTTON_THUMBL:
      return kSbKeyGamepadLeftStick;
    case AKEYCODE_BUTTON_THUMBR:
      return kSbKeyGamepadRightStick;
    case AKEYCODE_BUTTON_START:
      return kSbKeyGamepad6;
    case AKEYCODE_BUTTON_SELECT:
      return kSbKeyGamepad5;
    case AKEYCODE_BUTTON_MODE:
      return kSbKeyModechange;

    // Media transport
    case AKEYCODE_MEDIA_PLAY_PAUSE:
      return kSbKeyMediaPlayPause;
    case AKEYCODE_MEDIA_PLAY:
      return kSbKeyPlay;
    case AKEYCODE_MEDIA_PAUSE:
      return kSbKeyPause;
    case AKEYCODE_MEDIA_STOP:
      return kSbKeyMediaStop;
    case AKEYCODE_MEDIA_NEXT:
      return kSbKeyMediaNextTrack;
    case AKEYCODE_MEDIA_PREVIOUS:
      return kSbKeyMediaPrevTrack;
    case AKEYCODE_MEDIA_REWIND:
      return kSbKeyMediaRewind;
    case AKEYCODE_MEDIA_FAST_FORWARD:
      return kSbKeyMediaFastForward;

    // TV Remote specific
    case AKEYCODE_CHANNEL_UP:
      return kSbKeyChannelUp;
    case AKEYCODE_CHANNEL_DOWN:
      return kSbKeyChannelDown;
    case AKEYCODE_CAPTIONS:
      return kSbKeyClosedCaption;
    case AKEYCODE_INFO:
      return kSbKeyInfo;
    case AKEYCODE_GUIDE:
      return kSbKeyGuide;
    case AKEYCODE_LAST_CHANNEL:
      return kSbKeyLast;
    case AKEYCODE_MEDIA_AUDIO_TRACK:
      return kSbKeyMediaAudioTrack;

    case AKEYCODE_PROG_RED:
      return kSbKeyRed;
    case AKEYCODE_PROG_GREEN:
      return kSbKeyGreen;
    case AKEYCODE_PROG_YELLOW:
      return kSbKeyYellow;
    case AKEYCODE_PROG_BLUE:
      return kSbKeyBlue;

    // Whitespace
    case AKEYCODE_TAB:
      return kSbKeyTab;
    case AKEYCODE_SPACE:
      return kSbKeySpace;

    // Deletion
    case AKEYCODE_DEL:  // Backspace
      return kSbKeyBack;
    case AKEYCODE_FORWARD_DEL:
      return kSbKeyDelete;
    case AKEYCODE_CLEAR:
      return kSbKeyClear;

    // Insert
    case AKEYCODE_INSERT:
      return kSbKeyInsert;

    // Symbols
    case AKEYCODE_NUMPAD_ADD:
      return kSbKeyAdd;
    case AKEYCODE_PLUS:
    case AKEYCODE_EQUALS:
    case AKEYCODE_NUMPAD_EQUALS:
      return kSbKeyOemPlus;
    case AKEYCODE_NUMPAD_SUBTRACT:
      return kSbKeySubtract;
    case AKEYCODE_MINUS:
      return kSbKeyOemMinus;
    case AKEYCODE_NUMPAD_MULTIPLY:
      return kSbKeyMultiply;
    case AKEYCODE_NUMPAD_DIVIDE:
      return kSbKeyDivide;
    case AKEYCODE_COMMA:
    case AKEYCODE_NUMPAD_COMMA:
      return kSbKeyOemComma;
    case AKEYCODE_NUMPAD_DOT:
      return kSbKeyDecimal;
    case AKEYCODE_PERIOD:
      return kSbKeyOemPeriod;
    case AKEYCODE_SEMICOLON:
      return kSbKeyOem1;
    case AKEYCODE_SLASH:
      return kSbKeyOem2;
    case AKEYCODE_GRAVE:
      return kSbKeyOem3;
    case AKEYCODE_LEFT_BRACKET:
      return kSbKeyOem4;
    case AKEYCODE_BACKSLASH:
      return kSbKeyOem5;
    case AKEYCODE_RIGHT_BRACKET:
      return kSbKeyOem6;
    case AKEYCODE_APOSTROPHE:
      return kSbKeyOem7;

    // Function keys
    case AKEYCODE_F1:
    case AKEYCODE_F2:
    case AKEYCODE_F3:
    case AKEYCODE_F4:
    case AKEYCODE_F5:
    case AKEYCODE_F6:
    case AKEYCODE_F7:
    case AKEYCODE_F8:
    case AKEYCODE_F9:
    case AKEYCODE_F10:
    case AKEYCODE_F11:
    case AKEYCODE_F12:
      return static_cast<SbKey>(kSbKeyF1 + (keycode - AKEYCODE_F1));

    // Digits
    case AKEYCODE_0:
    case AKEYCODE_1:
    case AKEYCODE_2:
    case AKEYCODE_3:
    case AKEYCODE_4:
    case AKEYCODE_5:
    case AKEYCODE_6:
    case AKEYCODE_7:
    case AKEYCODE_8:
    case AKEYCODE_9:
      return static_cast<SbKey>(kSbKey0 + (keycode - AKEYCODE_0));

    // Numpad digits
    case AKEYCODE_NUMPAD_0:
    case AKEYCODE_NUMPAD_1:
    case AKEYCODE_NUMPAD_2:
    case AKEYCODE_NUMPAD_3:
    case AKEYCODE_NUMPAD_4:
    case AKEYCODE_NUMPAD_5:
    case AKEYCODE_NUMPAD_6:
    case AKEYCODE_NUMPAD_7:
    case AKEYCODE_NUMPAD_8:
    case AKEYCODE_NUMPAD_9:
      return static_cast<SbKey>(kSbKeyNumpad0 + (keycode - AKEYCODE_NUMPAD_0));

    // Alphabetic
    case AKEYCODE_A:
    case AKEYCODE_B:
    case AKEYCODE_C:
    case AKEYCODE_D:
    case AKEYCODE_E:
    case AKEYCODE_F:
    case AKEYCODE_G:
    case AKEYCODE_H:
    case AKEYCODE_I:
    case AKEYCODE_J:
    case AKEYCODE_K:
    case AKEYCODE_L:
    case AKEYCODE_M:
    case AKEYCODE_N:
    case AKEYCODE_O:
    case AKEYCODE_P:
    case AKEYCODE_Q:
    case AKEYCODE_R:
    case AKEYCODE_S:
    case AKEYCODE_T:
    case AKEYCODE_U:
    case AKEYCODE_V:
    case AKEYCODE_W:
    case AKEYCODE_X:
    case AKEYCODE_Y:
    case AKEYCODE_Z:
      return static_cast<SbKey>(kSbKeyA + (keycode - AKEYCODE_A));

    // Don't handle these keys so the OS can in a uniform manner.
    case AKEYCODE_VOLUME_UP:
    case AKEYCODE_VOLUME_DOWN:
    case AKEYCODE_MUTE:
    case AKEYCODE_BRIGHTNESS_UP:
    case AKEYCODE_BRIGHTNESS_DOWN:
    case AKEYCODE_SEARCH:
    default:
      return kSbKeyUnknown;
  }
}

}  // namespace

InputEventsGenerator::InputEventsGenerator(SbWindow window)
    : window_(window),
      hat_value_(),
      left_thumbstick_key_pressed_{kSbKeyUnknown, kSbKeyUnknown} {
  SB_DCHECK(SbWindowIsValid(window_));
}

InputEventsGenerator::~InputEventsGenerator() {}

// For a left joystick, AMOTION_EVENT_AXIS_X reports the absolute X position of
// the joystick. The value is normalized to a range from -1.0 (left) to 1.0
// (right).
//
// For a left joystick, AMOTION_EVENT_AXIS_Y reports the absolute Y position of
// the joystick. The value is normalized to a range from -1.0 (up or far) to 1.0
// (down or near).
//
// On game pads with two analog joysticks, AMOTION_EVENT_AXIS_Z is often
// reinterpreted to report the absolute X position of the second joystick.
//
// On game pads with two analog joysticks, AMOTION_EVENT_AXIS_RZ is often
// reinterpreted to report the absolute Y position of the second joystick.
void InputEventsGenerator::ProcessJoyStickEvent(FlatAxis axis,
                                                int32_t motion_axis,
                                                AInputEvent* android_event,
                                                Events* events) {
  SB_DCHECK(AMotionEvent_getPointerCount(android_event) > 0);

  int32_t device_id = AInputEvent_getDeviceId(android_event);
  SB_DCHECK(device_flat_.find(device_id) != device_flat_.end());

  float flat = device_flat_[device_id][axis];
  float offset = AMotionEvent_getAxisValue(android_event, motion_axis, 0);
  int sign = offset < 0.0f ? -1 : 1;

  if (fabs(offset) < flat) {
    offset = sign * flat;
  }
  // Rescaled the range:
  // [-1.0f, -flat] to [-1.0f, 0.0f] and [flat, 1.0f] to [0.0f, 1.0f]
  offset = (offset - sign * flat) / (1 - flat);

  // Report up and left as negative values.
  SbInputVector input_vector;
  SbKey key = kSbKeyUnknown;
  SbKeyLocation location = kSbKeyLocationUnspecified;
  switch (axis) {
    case kLeftX: {
      input_vector.x = offset;
      input_vector.y = 0.0f;
      key = kSbKeyGamepadLeftStickLeft;
      location = kSbKeyLocationLeft;
      break;
    }
    case kLeftY: {
      input_vector.x = 0.0f;
      input_vector.y = offset;
      key = kSbKeyGamepadLeftStickUp;
      location = kSbKeyLocationLeft;
      break;
    }
    case kRightX: {
      input_vector.x = offset;
      input_vector.y = 0.0f;
      key = kSbKeyGamepadRightStickLeft;
      location = kSbKeyLocationRight;
      break;
    }
    case kRightY: {
      input_vector.x = 0.0f;
      input_vector.y = offset;
      key = kSbKeyGamepadRightStickUp;
      location = kSbKeyLocationRight;
      break;
    }
    default:
      SB_NOTREACHED();
  }

  events->push_back(
      CreateMoveEventWithKey(device_id, window_, key, location, input_vector));
}

namespace {

// Generate a Starboard event from an Android event, with the SbKey and
// SbInputEventType pre-specified (so that it can be used by event
// synthesization as well.)
void PushKeyEvent(SbKey key,
                  SbInputEventType type,
                  SbWindow window,
                  AInputEvent* android_event,
                  Events* events) {
  if (key == kSbKeyUnknown) {
    SB_NOTREACHED();
    return;
  }

  std::unique_ptr<SbInputData> data(new SbInputData());
  memset(data.get(), 0, sizeof(*data));

  // window
  data->window = window;
  data->type = type;

  // device
  // TODO: differentiate gamepad, remote, etc.
  data->device_type = kSbInputDeviceTypeKeyboard;
  data->device_id = AInputEvent_getDeviceId(android_event);

  // key
  data->key = key;
  data->key_location = AInputEventToSbKeyLocation(android_event);
  data->key_modifiers = AInputEventToSbModifiers(android_event);

  std::unique_ptr<Event> event(
      new Event(kSbEventTypeInput, data.release(),
                &Application::DeleteDestructor<SbInputData>));
  events->push_back(std::move(event));
}

// Some helper enumerations to index into the InputEventsGenerator::hat_value_
// array.
enum HatAxis {
  kHatX,
  kHatY,
};

struct HatValue {
  HatAxis axis;
  float value;
};

// Converts Starboard DPad direction keys to Starboard left thumbstick
// direction keys.
SbKey ConvertDPadKeyToThumbstickKey(SbKey key) {
  switch (key) {
    case kSbKeyGamepadDPadUp:
      return kSbKeyGamepadLeftStickUp;
    case kSbKeyGamepadDPadDown:
      return kSbKeyGamepadLeftStickDown;
    case kSbKeyGamepadDPadLeft:
      return kSbKeyGamepadLeftStickLeft;
    case kSbKeyGamepadDPadRight:
      return kSbKeyGamepadLeftStickRight;
    default: {
      SB_NOTREACHED();
      return kSbKeyUnknown;
    }
  }
}

// Convert a Starboard DPad direction key to a (axis, direction) pair.
HatValue HatValueForDPadKey(SbKey key) {
  SB_DCHECK(IsDPadKey(key));

  switch (key) {
    case kSbKeyGamepadDPadUp:
      return HatValue({kHatY, -1.0f});
    case kSbKeyGamepadDPadDown:
      return HatValue({kHatY, 1.0f});
    case kSbKeyGamepadDPadLeft:
      return HatValue({kHatX, -1.0f});
    case kSbKeyGamepadDPadRight:
      return HatValue({kHatX, 1.0f});
    default: {
      SB_NOTREACHED();
      return HatValue({kHatX, 0.0f});
    }
  }
}

// The inverse of HatValueForDPadKey().
SbKey KeyForHatValue(const HatValue& hat_value) {
  SB_DCHECK(hat_value.value > 0.5f || hat_value.value < -0.5f);
  if (hat_value.axis == kHatX) {
    if (hat_value.value > 0.5f) {
      return kSbKeyGamepadDPadRight;
    } else {
      return kSbKeyGamepadDPadLeft;
    }
  } else if (hat_value.axis == kHatY) {
    if (hat_value.value > 0.5f) {
      return kSbKeyGamepadDPadDown;
    } else {
      return kSbKeyGamepadDPadUp;
    }
  } else {
    SB_NOTREACHED();
    return kSbKeyUnknown;
  }
}

// Analyzes old axis values and new axis values and fire off any synthesized
// key press/unpress events as necessary.
void PossiblySynthesizeHatKeyEvents(HatAxis axis,
                                    float old_value,
                                    float new_value,
                                    SbWindow window,
                                    AInputEvent* android_event,
                                    Events* events) {
  if (old_value == new_value) {
    // No events to generate if the hat motion value did not change.
    return;
  }

  if (old_value > 0.5f || old_value < -0.5f) {
    PushKeyEvent(KeyForHatValue(HatValue({axis, old_value})),
                 kSbInputEventTypeUnpress, window, android_event, events);
  }
  if (new_value > 0.5f || new_value < -0.5f) {
    PushKeyEvent(KeyForHatValue(HatValue({axis, new_value})),
                 kSbInputEventTypePress, window, android_event, events);
  }
}

}  // namespace

bool InputEventsGenerator::ProcessKeyEvent(AInputEvent* android_event,
                                           Events* events) {
#ifdef STARBOARD_INPUT_EVENTS_FILTER
  if (!input_events_filter_.ShouldProcessKeyEvent(android_event)) {
    return false;
  }
#endif

  SbInputEventType type;
  switch (AKeyEvent_getAction(android_event)) {
    case AKEY_EVENT_ACTION_DOWN:
      type = kSbInputEventTypePress;
      break;
    case AKEY_EVENT_ACTION_UP:
      type = kSbInputEventTypeUnpress;
      break;
    default:
      // TODO: send multiple events for AKEY_EVENT_ACTION_MULTIPLE
      return false;
  }

  SbKey key = AInputEventToSbKey(android_event);
  if (key == kSbKeyUnknown) {
    return false;
  }

  if (AKeyEvent_getFlags(android_event) & AKEY_EVENT_FLAG_FALLBACK &&
      IsDPadKey(key)) {
    // For fallback DPad keys, we flow into special processing to manage the
    // differentiation between the actual DPad and the left thumbstick, since
    // Android conflates the key down/up events for these inputs.
    ProcessFallbackDPadEvent(type, key, android_event, events);
  } else {
    PushKeyEvent(key, type, window_, android_event, events);
  }
  return true;
}

namespace {

SbKey ButtonStateToSbKey(int32_t button_state) {
  if (button_state & AMOTION_EVENT_BUTTON_PRIMARY) {
    return kSbKeyMouse1;
  } else if (button_state & AMOTION_EVENT_BUTTON_SECONDARY) {
    return kSbKeyMouse2;
  } else if (button_state & AMOTION_EVENT_BUTTON_TERTIARY) {
    return kSbKeyMouse3;
  } else if (button_state & AMOTION_EVENT_BUTTON_BACK) {
    return kSbKeyBrowserBack;
  } else if (button_state & AMOTION_EVENT_BUTTON_FORWARD) {
    return kSbKeyBrowserForward;
  }
  return kSbKeyUnknown;
}

// Get an SbKeyModifiers from a button state
unsigned int ButtonStateToSbModifiers(unsigned int button_state) {
  unsigned int key_modifiers = kSbKeyModifiersNone;
  if (button_state & AMOTION_EVENT_BUTTON_PRIMARY) {
    key_modifiers |= kSbKeyModifiersPointerButtonLeft;
  }
  if (button_state & AMOTION_EVENT_BUTTON_SECONDARY) {
    key_modifiers |= kSbKeyModifiersPointerButtonMiddle;
  }
  if (button_state & AMOTION_EVENT_BUTTON_TERTIARY) {
    key_modifiers |= kSbKeyModifiersPointerButtonRight;
  }
  if (button_state & AMOTION_EVENT_BUTTON_BACK) {
    key_modifiers |= kSbKeyModifiersPointerButtonBack;
  }
  if (button_state & AMOTION_EVENT_BUTTON_FORWARD) {
    key_modifiers |= kSbKeyModifiersPointerButtonForward;
  }
  return key_modifiers;
}

}  // namespace

bool InputEventsGenerator::ProcessPointerEvent(AInputEvent* android_event,
                                               Events* events) {
  float offset_x =
      AMotionEvent_getAxisValue(android_event, AMOTION_EVENT_AXIS_X, 0);
  float offset_y =
      AMotionEvent_getAxisValue(android_event, AMOTION_EVENT_AXIS_Y, 0);

  std::unique_ptr<SbInputData> data(new SbInputData());
  memset(data.get(), 0, sizeof(*data));

  data->window = window_;
  SB_DCHECK(SbWindowIsValid(data->window));
  data->pressure = NAN;
  data->size = {NAN, NAN};
  data->tilt = {NAN, NAN};
  unsigned int button_state = AMotionEvent_getButtonState(android_event);
  unsigned int button_modifiers = ButtonStateToSbModifiers(button_state);

  // Default to reporting pointer events as mouse events.
  data->device_type = kSbInputDeviceTypeMouse;

  // Report both stylus and touchscreen events as touchscreen device events.
  int32_t event_source = AInputEvent_getSource(android_event);
  if (((event_source & AINPUT_SOURCE_TOUCHSCREEN) != 0) ||
      ((event_source & AINPUT_SOURCE_STYLUS) != 0)) {
    data->device_type = kSbInputDeviceTypeTouchScreen;
  }

  data->device_id = AInputEvent_getDeviceId(android_event);
  data->key_modifiers =
      button_modifiers | AInputEventToSbModifiers(android_event);
  data->position.x = offset_x;
  data->position.y = offset_y;
  data->key = ButtonStateToSbKey(button_state);

  switch (AKeyEvent_getAction(android_event) & AMOTION_EVENT_ACTION_MASK) {
    case AMOTION_EVENT_ACTION_UP:
      data->type = kSbInputEventTypeUnpress;
      break;
    case AMOTION_EVENT_ACTION_DOWN:
      data->type = kSbInputEventTypePress;
      break;
    case AMOTION_EVENT_ACTION_MOVE:
    case AMOTION_EVENT_ACTION_HOVER_MOVE:
      data->type = kSbInputEventTypeMove;
      break;
    case AMOTION_EVENT_ACTION_SCROLL: {
      float hscroll = AMotionEvent_getAxisValue(
          android_event, AMOTION_EVENT_AXIS_HSCROLL, 0);  // left is -1
      float vscroll = AMotionEvent_getAxisValue(
          android_event, AMOTION_EVENT_AXIS_VSCROLL, 0);  // down is -1
      float wheel =
          AMotionEvent_getAxisValue(android_event, AMOTION_EVENT_AXIS_WHEEL, 0);
      data->type = kSbInputEventTypeWheel;
      data->key = kSbKeyUnknown;
      data->delta.y = -vscroll;
      data->delta.x = hscroll;
      break;
    }
    default:
      return false;
  }

  events->push_back(std::unique_ptr<Event>(
      new Application::Event(kSbEventTypeInput, data.release(),
                             &Application::DeleteDestructor<SbInputData>)));
  return true;
}

bool InputEventsGenerator::ProcessMotionEvent(AInputEvent* android_event,
                                              Events* events) {
  int32_t event_source = AInputEvent_getSource(android_event);
  if ((event_source & AINPUT_SOURCE_CLASS_POINTER) != 0) {
    return ProcessPointerEvent(android_event, events);
  }
  if ((event_source & AINPUT_SOURCE_JOYSTICK) == 0) {
    // Only handles joystick events in the code below.
    return false;
  }

  UpdateDeviceFlatMapIfNecessary(android_event);
  ProcessJoyStickEvent(kLeftX, AMOTION_EVENT_AXIS_X, android_event, events);
  ProcessJoyStickEvent(kLeftY, AMOTION_EVENT_AXIS_Y, android_event, events);
  ProcessJoyStickEvent(kRightX, AMOTION_EVENT_AXIS_Z, android_event, events);
  ProcessJoyStickEvent(kRightY, AMOTION_EVENT_AXIS_RZ, android_event, events);

  // Remember the "hat" input values (dpad on the game controller) to help
  // differentiate hat vs. stick fallback events.
  UpdateHatValuesAndPossiblySynthesizeKeyEvents(android_event, events);

  // Lie to Android and tell it that we did not process the motion event,
  // causing Android to synthesize dpad key events for us. When we handle
  // those synthesized key events we'll enqueue kSbKeyGamepadLeft rather
  // than kSbKeyGamepadDPad events if they're from the joystick.
  return false;
}

// Special processing to disambiguate between DPad events and left-thumbstick
// direction key events.
void InputEventsGenerator::ProcessFallbackDPadEvent(SbInputEventType type,
                                                    SbKey key,
                                                    AInputEvent* android_event,
                                                    Events* events) {
  SB_DCHECK(AKeyEvent_getFlags(android_event) & AKEY_EVENT_FLAG_FALLBACK);
  SB_DCHECK(IsDPadKey(key));

  HatAxis hat_axis = HatValueForDPadKey(key).axis;

  if (hat_value_[hat_axis] != 0.0f && type == kSbInputEventTypePress) {
    // Direction pad events are all assumed to be coming from the hat controls
    // if motion events for that hat DPAD is active, but we do still handle
    // repeat keys here.
    if (AKeyEvent_getRepeatCount(android_event) > 0) {
      SB_LOG(INFO) << AKeyEvent_getRepeatCount(android_event);
      PushKeyEvent(key, kSbInputEventTypePress, window_, android_event, events);
    }
    return;
  }

  // If we get this far, then we are exclusively dealing with thumbstick events,
  // as actual DPad events are processed in motion events by checking the
  // hat axis representing the DPad.
  SbKey thumbstick_key = ConvertDPadKeyToThumbstickKey(key);

  if (left_thumbstick_key_pressed_[hat_axis] != kSbKeyUnknown &&
      (type == kSbInputEventTypeUnpress ||
       left_thumbstick_key_pressed_[hat_axis] != thumbstick_key)) {
    // Fire an unpressed event if our current key differs from the last seen
    // key.
    PushKeyEvent(left_thumbstick_key_pressed_[hat_axis],
                 kSbInputEventTypeUnpress, window_, android_event, events);
  }

  if (type == kSbInputEventTypePress) {
    PushKeyEvent(thumbstick_key, kSbInputEventTypePress, window_, android_event,
                 events);
    left_thumbstick_key_pressed_[hat_axis] = thumbstick_key;
  } else if (type == kSbInputEventTypeUnpress) {
    left_thumbstick_key_pressed_[hat_axis] = kSbKeyUnknown;
  } else {
    SB_NOTREACHED();
  }
}

// Update |InputEventsGenerator::hat_value_| according to the incoming motion
// event's data.  Possibly generate DPad events based on any changes in value
// here.
void InputEventsGenerator::UpdateHatValuesAndPossiblySynthesizeKeyEvents(
    AInputEvent* android_event,
    Events* events) {
  float new_hat_x =
      AMotionEvent_getAxisValue(android_event, AMOTION_EVENT_AXIS_HAT_X, 0);
  PossiblySynthesizeHatKeyEvents(kHatX, hat_value_[kHatX], new_hat_x, window_,
                                 android_event, events);
  hat_value_[kHatX] = new_hat_x;

  float new_hat_y =
      AMotionEvent_getAxisValue(android_event, AMOTION_EVENT_AXIS_HAT_Y, 0);
  PossiblySynthesizeHatKeyEvents(kHatY, hat_value_[kHatY], new_hat_y, window_,
                                 android_event, events);
  hat_value_[kHatY] = new_hat_y;
}

void InputEventsGenerator::UpdateDeviceFlatMapIfNecessary(
    AInputEvent* android_event) {
  int32_t device_id = AInputEvent_getDeviceId(android_event);
  if (device_flat_.find(device_id) != device_flat_.end()) {
    // |device_flat_| is already contains the device flat information.
    return;
  }

  JniEnvExt* env = JniEnvExt::Get();
  ScopedLocalJavaRef<jobject> input_device(env->CallStaticObjectMethodOrAbort(
      "android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;",
      device_id));
  float flats[kNumAxes] = {GetFlat(input_device.Get(), AMOTION_EVENT_AXIS_X),
                           GetFlat(input_device.Get(), AMOTION_EVENT_AXIS_Y),
                           GetFlat(input_device.Get(), AMOTION_EVENT_AXIS_Z),
                           GetFlat(input_device.Get(), AMOTION_EVENT_AXIS_RZ)};
  device_flat_[device_id] = std::vector<float>(flats, flats + kNumAxes);
}

bool InputEventsGenerator::CreateInputEventsFromAndroidEvent(
    AInputEvent* android_event,
    Events* events) {
  if (android_event == NULL ||
      (AInputEvent_getType(android_event) != AINPUT_EVENT_TYPE_KEY &&
       AInputEvent_getType(android_event) != AINPUT_EVENT_TYPE_MOTION)) {
    return false;
  }

  switch (AInputEvent_getType(android_event)) {
    case AINPUT_EVENT_TYPE_KEY:
      return ProcessKeyEvent(android_event, events);
    case AINPUT_EVENT_TYPE_MOTION: {
      return ProcessMotionEvent(android_event, events);
    }
    default:
      SB_NOTREACHED();
  }

  return false;
}

void InputEventsGenerator::CreateInputEventsFromSbKey(SbKey key,
                                                      Events* events) {
  events->clear();

  // Press event
  std::unique_ptr<SbInputData> data(new SbInputData());
  memset(data.get(), 0, sizeof(*data));

  data->window = window_;
  data->type = kSbInputEventTypePress;

  data->device_type = kSbInputDeviceTypeKeyboard;
  data->device_id = 0;

  data->key = key;
  data->key_location = kSbKeyLocationUnspecified;
  data->key_modifiers = kSbKeyModifiersNone;

  events->push_back(std::unique_ptr<Event>(
      new Application::Event(kSbEventTypeInput, data.release(),
                             &Application::DeleteDestructor<SbInputData>)));

  // Unpress event
  data.reset(new SbInputData());
  memset(data.get(), 0, sizeof(*data));

  data->window = window_;
  data->type = kSbInputEventTypeUnpress;

  data->device_type = kSbInputDeviceTypeKeyboard;
  data->device_id = 0;

  data->key = key;
  data->key_location = kSbKeyLocationUnspecified;
  data->key_modifiers = kSbKeyModifiersNone;

  events->push_back(std::unique_ptr<Event>(
      new Application::Event(kSbEventTypeInput, data.release(),
                             &Application::DeleteDestructor<SbInputData>)));
}

}  // namespace shared
}  // namespace android
}  // namespace starboard
