// 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.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()));
  }
}
}

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);
#if SB_API_VERSION >= 6
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);
#endif  // SB_API_VERSION >= 6

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());
#if SB_API_VERSION >= 6
  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));
#endif  // SB_API_VERSION >= 6
  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
