// Copyright 2015 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.

#include "remoting/host/touch_injector_win.h"

#include <utility>

#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/native_library.h"
#include "remoting/proto/event.pb.h"

namespace remoting {

using protocol::TouchEvent;
using protocol::TouchEventPoint;

namespace {

typedef BOOL(NTAPI* InitializeTouchInjectionFunction)(UINT32, DWORD);
typedef BOOL(NTAPI* InjectTouchInputFunction)(UINT32,
                                              const POINTER_TOUCH_INFO*);
const uint32_t kMaxSimultaneousTouchCount = 10;

// This is used to reinject all points that have not changed as "move"ed points,
// even if they have not actually moved.
// This is required for multi-touch to work, e.g. pinching and zooming gestures
// (handled by apps) won't work without reinjecting the points, even though the
// user moved only one finger and held the other finger in place.
void AppendMapValuesToVector(
    std::map<uint32_t, POINTER_TOUCH_INFO>* touches_in_contact,
    std::vector<POINTER_TOUCH_INFO>* output_vector) {
  for (auto& id_and_pointer_touch_info : *touches_in_contact) {
    POINTER_TOUCH_INFO& pointer_touch_info = id_and_pointer_touch_info.second;
    output_vector->push_back(pointer_touch_info);
  }
}

// The caller should set memset(0) the struct and set
// pointer_touch_info->pointerInfo.pointerFlags.
void ConvertToPointerTouchInfo(
    const TouchEventPoint& touch_point,
    POINTER_TOUCH_INFO* pointer_touch_info) {
  pointer_touch_info->touchMask =
      TOUCH_MASK_CONTACTAREA | TOUCH_MASK_ORIENTATION;
  pointer_touch_info->touchFlags = TOUCH_FLAG_NONE;

  // Although radius_{x,y} can be undefined (i.e. has_radius_{x,y} == false),
  // the default value (0.0) will set the area correctly.
  // MSDN mentions that if the digitizer does not detect the size of the touch
  // point, rcContact should be set to 0 by 0 rectangle centered at the
  // coordinate.
  pointer_touch_info->rcContact.left =
      touch_point.x() - touch_point.radius_x();
  pointer_touch_info->rcContact.top = touch_point.y() - touch_point.radius_y();
  pointer_touch_info->rcContact.right =
      touch_point.x() + touch_point.radius_x();
  pointer_touch_info->rcContact.bottom =
      touch_point.y() + touch_point.radius_y();

  pointer_touch_info->orientation = touch_point.angle();

  if (touch_point.has_pressure()) {
    pointer_touch_info->touchMask |= TOUCH_MASK_PRESSURE;
    const float kMinimumPressure = 0.0;
    const float kMaximumPressure = 1.0;
    const float clamped_touch_point_pressure =
        std::max(kMinimumPressure,
                 std::min(kMaximumPressure, touch_point.pressure()));

    const int kWindowsMaxTouchPressure = 1024;  // Defined in MSDN.
    const int pressure =
        clamped_touch_point_pressure * kWindowsMaxTouchPressure;
    pointer_touch_info->pressure = pressure;
  }

  pointer_touch_info->pointerInfo.pointerType = PT_TOUCH;
  pointer_touch_info->pointerInfo.pointerId = touch_point.id();
  pointer_touch_info->pointerInfo.ptPixelLocation.x = touch_point.x();
  pointer_touch_info->pointerInfo.ptPixelLocation.y = touch_point.y();
}

}  // namespace

TouchInjectorWinDelegate::~TouchInjectorWinDelegate() {}

// static.
std::unique_ptr<TouchInjectorWinDelegate> TouchInjectorWinDelegate::Create() {
  base::ScopedNativeLibrary library(base::FilePath(L"User32.dll"));
  if (!library.is_valid()) {
    PLOG(INFO) << "Failed to get library module for touch injection functions.";
    return std::unique_ptr<TouchInjectorWinDelegate>();
  }

  InitializeTouchInjectionFunction init_func =
      reinterpret_cast<InitializeTouchInjectionFunction>(
          library.GetFunctionPointer("InitializeTouchInjection"));
  if (!init_func) {
    PLOG(INFO) << "Failed to get InitializeTouchInjection function handle.";
    return std::unique_ptr<TouchInjectorWinDelegate>();
  }

  InjectTouchInputFunction inject_touch_func =
      reinterpret_cast<InjectTouchInputFunction>(
          library.GetFunctionPointer("InjectTouchInput"));
  if (!inject_touch_func) {
    PLOG(INFO) << "Failed to get InjectTouchInput.";
    return std::unique_ptr<TouchInjectorWinDelegate>();
  }

  return std::unique_ptr<TouchInjectorWinDelegate>(new TouchInjectorWinDelegate(
      library.Release(), init_func, inject_touch_func));
}

TouchInjectorWinDelegate::TouchInjectorWinDelegate(
    base::NativeLibrary library,
    InitializeTouchInjectionFunction initialize_touch_injection_func,
    InjectTouchInputFunction inject_touch_input_func)
    : library_module_(library),
      initialize_touch_injection_func_(initialize_touch_injection_func),
      inject_touch_input_func_(inject_touch_input_func) {}

BOOL TouchInjectorWinDelegate::InitializeTouchInjection(UINT32 max_count,
                                                        DWORD dw_mode) {
  return initialize_touch_injection_func_(max_count, dw_mode);
}

DWORD TouchInjectorWinDelegate::InjectTouchInput(
    UINT32 count,
    const POINTER_TOUCH_INFO* contacts) {
  return inject_touch_input_func_(count, contacts);
}

TouchInjectorWin::TouchInjectorWin()
    : delegate_(TouchInjectorWinDelegate::Create()) {}

TouchInjectorWin::~TouchInjectorWin() {}

// Note that TouchInjectorWinDelegate::Create() is not called in this method
// so that a mock delegate can be injected in tests and set expectations on the
// mock and return value of this method.
bool TouchInjectorWin::Init() {
  if (!delegate_)
    return false;

  if (!delegate_->InitializeTouchInjection(
          kMaxSimultaneousTouchCount, TOUCH_FEEDBACK_DEFAULT)) {
    // delagate_ is reset here so that the function that need the delegate
    // can check if it is null.
    delegate_.reset();
    PLOG(INFO) << "Failed to initialize touch injection.";
    return false;
  }

  return true;
}

void TouchInjectorWin::Deinitialize() {
  touches_in_contact_.clear();
  // Same reason as TouchInjectorWin::Init(). For injecting mock delegates for
  // tests, a new delegate is created here.
  delegate_ = TouchInjectorWinDelegate::Create();
}

void TouchInjectorWin::InjectTouchEvent(const TouchEvent& event) {
  if (!delegate_) {
    VLOG(3) << "Touch injection functions are not initialized.";
    return;
  }

  switch (event.event_type()) {
    case TouchEvent::TOUCH_POINT_START:
      AddNewTouchPoints(event);
      break;
    case TouchEvent::TOUCH_POINT_MOVE:
      MoveTouchPoints(event);
      break;
    case TouchEvent::TOUCH_POINT_END:
      EndTouchPoints(event);
      break;
    case TouchEvent::TOUCH_POINT_CANCEL:
      CancelTouchPoints(event);
      break;
    default:
      NOTREACHED();
      return;
  }
}

void TouchInjectorWin::SetInjectorDelegateForTest(
    std::unique_ptr<TouchInjectorWinDelegate> functions) {
  delegate_ = std::move(functions);
}

void TouchInjectorWin::AddNewTouchPoints(const TouchEvent& event) {
  DCHECK_EQ(event.event_type(), TouchEvent::TOUCH_POINT_START);

  std::vector<POINTER_TOUCH_INFO> touches;
  // Must inject already touching points as move events.
  AppendMapValuesToVector(&touches_in_contact_, &touches);

  for (const TouchEventPoint& touch_point : event.touch_points()) {
    POINTER_TOUCH_INFO pointer_touch_info;
    memset(&pointer_touch_info, 0, sizeof(pointer_touch_info));
    pointer_touch_info.pointerInfo.pointerFlags =
        POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_DOWN;
    ConvertToPointerTouchInfo(touch_point, &pointer_touch_info);
    touches.push_back(pointer_touch_info);

    // All points in the map should be a move point.
    pointer_touch_info.pointerInfo.pointerFlags =
        POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_UPDATE;
    touches_in_contact_[touch_point.id()] = pointer_touch_info;
  }

  if (delegate_->InjectTouchInput(touches.size(), touches.data()) == 0) {
    PLOG(ERROR) << "Failed to inject a touch start event.";
  }
}

void TouchInjectorWin::MoveTouchPoints(const TouchEvent& event) {
  DCHECK_EQ(event.event_type(), TouchEvent::TOUCH_POINT_MOVE);

  for (const TouchEventPoint& touch_point : event.touch_points()) {
    POINTER_TOUCH_INFO* pointer_touch_info =
        &touches_in_contact_[touch_point.id()];
    memset(pointer_touch_info, 0, sizeof(*pointer_touch_info));
    pointer_touch_info->pointerInfo.pointerFlags =
        POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_UPDATE;
    ConvertToPointerTouchInfo(touch_point, pointer_touch_info);
  }

  std::vector<POINTER_TOUCH_INFO> touches;
  // Must inject already touching points as move events.
  AppendMapValuesToVector(&touches_in_contact_, &touches);
  if (delegate_->InjectTouchInput(touches.size(), touches.data()) == 0) {
    PLOG(ERROR) << "Failed to inject a touch move event.";
  }
}

void TouchInjectorWin::EndTouchPoints(const TouchEvent& event) {
  DCHECK_EQ(event.event_type(), TouchEvent::TOUCH_POINT_END);

  std::vector<POINTER_TOUCH_INFO> touches;
  for (const TouchEventPoint& touch_point : event.touch_points()) {
    POINTER_TOUCH_INFO pointer_touch_info =
        touches_in_contact_[touch_point.id()];
    pointer_touch_info.pointerInfo.pointerFlags = POINTER_FLAG_UP;

    touches_in_contact_.erase(touch_point.id());
    touches.push_back(pointer_touch_info);
  }

  AppendMapValuesToVector(&touches_in_contact_, &touches);
  if (delegate_->InjectTouchInput(touches.size(), touches.data()) == 0) {
    PLOG(ERROR) << "Failed to inject a touch end event.";
  }
}

void TouchInjectorWin::CancelTouchPoints(const TouchEvent& event) {
  DCHECK_EQ(event.event_type(), TouchEvent::TOUCH_POINT_CANCEL);

  std::vector<POINTER_TOUCH_INFO> touches;
  for (const TouchEventPoint& touch_point : event.touch_points()) {
    POINTER_TOUCH_INFO pointer_touch_info =
        touches_in_contact_[touch_point.id()];
    pointer_touch_info.pointerInfo.pointerFlags =
        POINTER_FLAG_UP | POINTER_FLAG_CANCELED;

    touches_in_contact_.erase(touch_point.id());
    touches.push_back(pointer_touch_info);
  }

  AppendMapValuesToVector(&touches_in_contact_, &touches);
  if (delegate_->InjectTouchInput(touches.size(), touches.data()) == 0) {
    PLOG(ERROR) << "Failed to inject a touch cancel event.";
  }
}

}  // namespace remoting
