// Copyright 2015 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 "cobalt/input/input_device_manager_desktop.h"

#include <cmath>
#include <string>

#include "base/time/time.h"
#include "cobalt/base/token.h"
#include "cobalt/base/tokens.h"
#include "cobalt/dom/event.h"
#include "cobalt/dom/input_event.h"
#include "cobalt/dom/input_event_init.h"
#include "cobalt/dom/keyboard_event.h"
#include "cobalt/dom/keyboard_event_init.h"
#include "cobalt/dom/pointer_event.h"
#include "cobalt/dom/pointer_event_init.h"
#include "cobalt/dom/wheel_event.h"
#include "cobalt/dom/wheel_event_init.h"
#include "cobalt/input/create_default_camera_3d.h"
#include "cobalt/input/input_poller_impl.h"
#include "cobalt/overlay_info/overlay_info_registry.h"
#include "cobalt/system_window/input_event.h"

namespace cobalt {
namespace input {

namespace {
void UpdateEventInit(const system_window::InputEvent* input_event,
                     EventInit* event) {
  if (input_event->timestamp() != 0) {
    // Convert SbTimeMonotonic to DOMTimeStamp.
    event->set_time_stamp(
        cobalt::dom::Event::GetEventTime(input_event->timestamp()));
  }
}
}  // namespace

InputDeviceManagerDesktop::InputDeviceManagerDesktop(
    const KeyboardEventCallback& keyboard_event_callback,
    const PointerEventCallback& pointer_event_callback,
    const WheelEventCallback& wheel_event_callback,
#if SB_HAS(ON_SCREEN_KEYBOARD)
    const InputEventCallback& input_event_callback,
#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
    system_window::SystemWindow* system_window)
    : system_window_(system_window),
      system_window_input_event_callback_(
          base::Bind(&InputDeviceManagerDesktop::HandleSystemWindowInputEvent,
                     base::Unretained(this))),
#if SB_HAS(ON_SCREEN_KEYBOARD)
      input_event_callback_(input_event_callback),
#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
      keypress_generator_filter_(keyboard_event_callback),
      pointer_event_callback_(pointer_event_callback),
      wheel_event_callback_(wheel_event_callback) {
  input_poller_ = new InputPollerImpl();
  DCHECK(system_window_);
  camera_3d_ =
      CreatedDefaultCamera3D(system_window->GetSbWindow(), input_poller_);

  if (system_window_) {
    // Add this object's keyboard event callback to the system window.
    system_window_->event_dispatcher()->AddEventCallback(
        system_window::InputEvent::TypeId(),
        system_window_input_event_callback_);
  }
}

InputDeviceManagerDesktop::~InputDeviceManagerDesktop() {
  // If we have an associated system window, remove our callback from it.
  if (system_window_) {
    system_window_->event_dispatcher()->RemoveEventCallback(
        system_window::InputEvent::TypeId(),
        system_window_input_event_callback_);
  }
}

namespace {

COMPILE_ASSERT(static_cast<uint32_t>(kSbKeyModifiersNone) ==
                       system_window::InputEvent::kNoModifier &&
                   static_cast<uint32_t>(kSbKeyModifiersAlt) ==
                       system_window::InputEvent::kAltKey &&
                   static_cast<uint32_t>(kSbKeyModifiersCtrl) ==
                       system_window::InputEvent::kCtrlKey &&
                   static_cast<uint32_t>(kSbKeyModifiersMeta) ==
                       system_window::InputEvent::kMetaKey &&
                   static_cast<uint32_t>(kSbKeyModifiersShift) ==
                       system_window::InputEvent::kShiftKey,
               Mismatched_modifier_enums);
COMPILE_ASSERT(static_cast<uint32_t>(kSbKeyModifiersPointerButtonLeft) ==
                       system_window::InputEvent::kLeftButton &&
                   static_cast<uint32_t>(kSbKeyModifiersPointerButtonRight) ==
                       system_window::InputEvent::kRightButton &&
                   static_cast<uint32_t>(kSbKeyModifiersPointerButtonMiddle) ==
                       system_window::InputEvent::kMiddleButton &&
                   static_cast<uint32_t>(kSbKeyModifiersPointerButtonBack) ==
                       system_window::InputEvent::kBackButton &&
                   static_cast<uint32_t>(kSbKeyModifiersPointerButtonForward) ==
                       system_window::InputEvent::kForwardButton,
               Mismatched_modifier_enums);

void UpdateEventModifierInit(const system_window::InputEvent* input_event,
                             EventModifierInit* event) {
  const uint32 modifiers = input_event->modifiers();
  event->set_ctrl_key(modifiers & system_window::InputEvent::kCtrlKey);
  event->set_shift_key(modifiers & system_window::InputEvent::kShiftKey);
  event->set_alt_key(modifiers & system_window::InputEvent::kAltKey);
  event->set_meta_key(modifiers & system_window::InputEvent::kMetaKey);
}

void UpdateMouseEventInitButtons(const system_window::InputEvent* input_event,
                                 MouseEventInit* event) {
  // The value of the button attribute MUST be as follows:
  //  https://www.w3.org/TR/uievents/#ref-for-dom-mouseevent-button-1
  switch (input_event->key_code()) {
    case kSbKeyMouse1:
      // 0 MUST indicate the primary button of the device (in general, the left
      // button or the only button on single-button devices, used to activate a
      // user interface control or select text) or the un-initialized value.
      event->set_button(0);
      break;
    case kSbKeyMouse2:
      // 1 MUST indicate the auxiliary button (in general, the middle button,
      // often combined with a mouse wheel).
      event->set_button(1);
      break;
    case kSbKeyMouse3:
      // 2 MUST indicate the secondary button (in general, the right button,
      // often used to display a context menu).
      event->set_button(2);
      break;
    default:
      break;
  }

  // The value of the buttons attribute MUST be as follows:
  //  https://www.w3.org/TR/uievents/#ref-for-dom-mouseevent-buttons-3

  // 0 MUST indicate no button is currently active.
  uint32 modifiers = input_event->modifiers();
  uint16 buttons = 0;
  if (modifiers & system_window::InputEvent::kLeftButton) {
    // 1 MUST indicate the primary button of the device (in general, the left
    // button or the only button on single-button devices, used to activate a
    // user interface control or select text).
    buttons |= 1;
  }
  if (modifiers & system_window::InputEvent::kRightButton) {
    // 2 MUST indicate the secondary button (in general, the right button, often
    // used to display a context menu), if present.
    buttons |= 2;
  }
  if (modifiers & system_window::InputEvent::kMiddleButton) {
    // 4 MUST indicate the auxiliary button (in general, the middle button,
    // often combined with a mouse wheel).
    buttons |= 4;
  }

  // The buttons attribute reflects the state of the mouse's buttons for any
  // MouseEvent object (while it is being dispatched).
  //   https://www.w3.org/TR/2016/WD-uievents-20160804/#ref-for-dom-mouseevent-buttons-2
  switch (input_event->type()) {
    case system_window::InputEvent::kTouchpadDown:
    case system_window::InputEvent::kTouchscreenDown:
    case system_window::InputEvent::kPointerDown:
      // For 'down' events, ensure that the buttons state includes the currently
      // reported button press.
      buttons |= 1 << event->button();
      break;
    case system_window::InputEvent::kTouchpadUp:
    case system_window::InputEvent::kTouchscreenUp:
    case system_window::InputEvent::kPointerUp:
      // For 'up' events, ensure that the buttons state excludes the currently
      // reported button press.
      buttons &= ~(1 << event->button());
      break;
    case system_window::InputEvent::kKeyDown:
    case system_window::InputEvent::kKeyUp:
    case system_window::InputEvent::kKeyMove:
    case system_window::InputEvent::kInput:
    case system_window::InputEvent::kPointerMove:
    case system_window::InputEvent::kTouchpadMove:
    case system_window::InputEvent::kTouchscreenMove:
    case system_window::InputEvent::kWheel:
      break;
  }

  event->set_buttons(buttons);
}

void UpdateMouseEventInit(const system_window::InputEvent* input_event,
                          dom::MouseEventInit* mouse_event) {
  UpdateEventModifierInit(input_event, mouse_event);
  UpdateMouseEventInitButtons(input_event, mouse_event);

  const math::PointF& position = input_event->position();
  mouse_event->set_screen_x(static_cast<float>(position.x()));
  mouse_event->set_screen_y(static_cast<float>(position.y()));
  mouse_event->set_client_x(static_cast<float>(position.x()));
  mouse_event->set_client_y(static_cast<float>(position.y()));
}

// Returns the value or the default_value when value is NaN.
float value_or(float value, float default_value) {
  return std::isnan(value) ? default_value : value;
}
}  // namespace

void InputDeviceManagerDesktop::HandleKeyboardEvent(
    bool is_key_down, const system_window::InputEvent* input_event,
    int key_code) {
  base::Token type =
      is_key_down ? base::Tokens::keydown() : base::Tokens::keyup();
  dom::KeyboardEvent::KeyLocationCode location =
      dom::KeyboardEvent::KeyCodeToKeyLocation(key_code);
  dom::KeyboardEventInit keyboard_event;
  UpdateEventInit(input_event, &keyboard_event);
  UpdateEventModifierInit(input_event, &keyboard_event);
  keyboard_event.set_location(location);
  keyboard_event.set_repeat(input_event->is_repeat());
  keyboard_event.set_char_code(key_code);
  keyboard_event.set_key_code(key_code);
  keypress_generator_filter_.HandleKeyboardEvent(type, keyboard_event);

  int32_t key_code_in_int32 = static_cast<int32_t>(key_code);
  overlay_info::OverlayInfoRegistry::Register(
      "input_manager:keydown", &key_code_in_int32, sizeof(key_code_in_int32));
}

void InputDeviceManagerDesktop::HandlePointerEvent(
    base::Token type, const system_window::InputEvent* input_event) {
  dom::PointerEventInit pointer_event;
  UpdateEventInit(input_event, &pointer_event);
  UpdateMouseEventInit(input_event, &pointer_event);

  switch (input_event->type()) {
    case system_window::InputEvent::kTouchpadDown:
    case system_window::InputEvent::kTouchpadUp:
    case system_window::InputEvent::kTouchpadMove:
      pointer_event.set_pointer_type("touchpad");
      break;
    case system_window::InputEvent::kTouchscreenDown:
    case system_window::InputEvent::kTouchscreenUp:
    case system_window::InputEvent::kTouchscreenMove:
      pointer_event.set_pointer_type("touch");
      break;
    case system_window::InputEvent::kKeyDown:
    case system_window::InputEvent::kKeyUp:
    case system_window::InputEvent::kKeyMove:
    case system_window::InputEvent::kInput:
    case system_window::InputEvent::kPointerDown:
    case system_window::InputEvent::kPointerMove:
    case system_window::InputEvent::kPointerUp:
    case system_window::InputEvent::kWheel:
      pointer_event.set_pointer_type("mouse");
      break;
  }
  pointer_event.set_pointer_id(input_event->device_id());
  pointer_event.set_width(value_or(input_event->size().x(), 0.0f));
  pointer_event.set_height(value_or(input_event->size().y(), 0.0f));
  pointer_event.set_pressure(value_or(input_event->pressure(),
                                      input_event->modifiers() ? 0.5f : 0.0f));
  pointer_event.set_tilt_x(
      value_or(static_cast<float>(input_event->tilt().x()), 0.0f));
  pointer_event.set_tilt_y(
      value_or(static_cast<float>(input_event->tilt().y()), 0.0f));
  pointer_event.set_is_primary(true);
  pointer_event_callback_.Run(type, pointer_event);
}

void InputDeviceManagerDesktop::HandleWheelEvent(
    const system_window::InputEvent* input_event) {
  base::Token type = base::Tokens::wheel();
  dom::WheelEventInit wheel_event;
  UpdateEventInit(input_event, &wheel_event);
  UpdateMouseEventInit(input_event, &wheel_event);

  wheel_event.set_delta_x(input_event->delta().x());
  wheel_event.set_delta_y(input_event->delta().y());
  wheel_event.set_delta_z(0);
  wheel_event.set_delta_mode(dom::WheelEvent::kDomDeltaLine);

  wheel_event_callback_.Run(type, wheel_event);
}

#if SB_HAS(ON_SCREEN_KEYBOARD)
void InputDeviceManagerDesktop::HandleInputEvent(
    const system_window::InputEvent* event) {
  // Note: we currently treat all dom::InputEvents as input (never beforeinput).
  base::Token type = base::Tokens::input();

  dom::InputEventInit input_event;
  UpdateEventInit(event, &input_event);
  input_event.set_data(event->input_text());
  input_event.set_is_composing(event->is_composing());
  input_event_callback_.Run(type, input_event);
}
#endif  // SB_HAS(ON_SCREEN_KEYBOARD)

void InputDeviceManagerDesktop::HandleSystemWindowInputEvent(
    const base::Event* event) {
  // The user has pressed a key on the keyboard.
  const system_window::InputEvent* input_event =
      base::polymorphic_downcast<const system_window::InputEvent*>(event);
  SB_DCHECK(input_event);
  int key_code = input_event->key_code();

  switch (input_event->type()) {
    case system_window::InputEvent::kKeyDown:
      HandleKeyboardEvent(true, input_event, key_code);
      break;
    case system_window::InputEvent::kKeyUp:
      HandleKeyboardEvent(false, input_event, key_code);
      break;
    case system_window::InputEvent::kPointerDown:
    case system_window::InputEvent::kPointerUp: {
      if ((kSbKeyBrowserBack == key_code) ||
          (kSbKeyBrowserForward == key_code) || (kSbKeyMouse2 == key_code)) {
        // For consistency with behavior on current browsers, the 'Forward' and
        // 'Back' mouse buttons are reported as keypress input for the 'Forward'
        // and 'Back' navigation keys, not as Pointer Events for the X1 and X2
        // buttons.

        if (kSbKeyMouse2 == key_code) {
          // Temporarily Report middle button presses as the enter key.
          key_code = kSbKeyReturn;
        }
        HandleKeyboardEvent(
            input_event->type() == system_window::InputEvent::kPointerDown,
            input_event, key_code);
      } else {
        base::Token type =
            input_event->type() == system_window::InputEvent::kPointerDown
                ? base::Tokens::pointerdown()
                : base::Tokens::pointerup();
        HandlePointerEvent(type, input_event);
      }
      break;
    }
    case system_window::InputEvent::kPointerMove:
    case system_window::InputEvent::kTouchpadMove:
    case system_window::InputEvent::kTouchscreenMove: {
      HandlePointerEvent(base::Tokens::pointermove(), input_event);
      break;
    }
    case system_window::InputEvent::kTouchpadDown:
    case system_window::InputEvent::kTouchscreenDown:
      HandlePointerEvent(base::Tokens::pointerdown(), input_event);
      break;
    case system_window::InputEvent::kTouchpadUp:
    case system_window::InputEvent::kTouchscreenUp:
      HandlePointerEvent(base::Tokens::pointerup(), input_event);
      break;
    case system_window::InputEvent::kWheel:
      HandleWheelEvent(input_event);
      break;
    case system_window::InputEvent::kInput:
#if SB_HAS(ON_SCREEN_KEYBOARD)
      HandleInputEvent(input_event);
      break;
#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
    case system_window::InputEvent::kKeyMove:
      break;
  }

  InputPollerImpl* input_poller_impl =
      static_cast<InputPollerImpl*>(input_poller_.get());
  input_poller_impl->UpdateInputEvent(input_event);
}

}  // namespace input
}  // namespace cobalt
