// Copyright 2014 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 "device/gamepad/raw_input_data_fetcher_win.h"

#include <stddef.h>

#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "device/gamepad/gamepad_standard_mappings.h"

namespace device {

namespace {

const uint16_t DeviceUsages[] = {
    RawInputGamepadDeviceWin::kGenericDesktopJoystick,
    RawInputGamepadDeviceWin::kGenericDesktopGamePad,
    RawInputGamepadDeviceWin::kGenericDesktopMultiAxisController,
};

}  // namespace

RawInputDataFetcher::RawInputDataFetcher() = default;

RawInputDataFetcher::~RawInputDataFetcher() {
  StopMonitor();
  ClearControllers();
  DCHECK(!window_);
  DCHECK(!events_monitored_);
}

GamepadSource RawInputDataFetcher::source() {
  return Factory::static_source();
}

void RawInputDataFetcher::OnAddedToProvider() {
  hid_functions_ = std::make_unique<HidDllFunctionsWin>();
  rawinput_available_ = hid_functions_->IsValid();
}

RAWINPUTDEVICE* RawInputDataFetcher::GetRawInputDevices(DWORD flags) {
  size_t usage_count = arraysize(DeviceUsages);
  std::unique_ptr<RAWINPUTDEVICE[]> devices(new RAWINPUTDEVICE[usage_count]);
  for (size_t i = 0; i < usage_count; ++i) {
    devices[i].dwFlags = flags;
    devices[i].usUsagePage = 1;
    devices[i].usUsage = DeviceUsages[i];
    devices[i].hwndTarget = (flags & RIDEV_REMOVE) ? 0 : window_->hwnd();
  }
  return devices.release();
}

void RawInputDataFetcher::PauseHint(bool pause) {
  if (pause)
    StopMonitor();
  else
    StartMonitor();
}

void RawInputDataFetcher::StartMonitor() {
  if (!rawinput_available_ || events_monitored_)
    return;

  if (!window_) {
    window_.reset(new base::win::MessageWindow());
    if (!window_->Create(base::Bind(&RawInputDataFetcher::HandleMessage,
                                    base::Unretained(this)))) {
      PLOG(ERROR) << "Failed to create the raw input window";
      window_.reset();
      return;
    }
  }

  // Register to receive raw HID input.
  std::unique_ptr<RAWINPUTDEVICE[]> devices(
      GetRawInputDevices(RIDEV_INPUTSINK));
  if (!::RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages),
                                 sizeof(RAWINPUTDEVICE))) {
    PLOG(ERROR) << "RegisterRawInputDevices() failed for RIDEV_INPUTSINK";
    window_.reset();
    return;
  }

  events_monitored_ = true;
}

void RawInputDataFetcher::StopMonitor() {
  if (!rawinput_available_ || !events_monitored_)
    return;

  // Stop receiving raw input.
  DCHECK(window_);
  std::unique_ptr<RAWINPUTDEVICE[]> devices(GetRawInputDevices(RIDEV_REMOVE));

  if (!::RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages),
                                 sizeof(RAWINPUTDEVICE))) {
    PLOG(INFO) << "RegisterRawInputDevices() failed for RIDEV_REMOVE";
  }

  events_monitored_ = false;
  window_.reset();
}

void RawInputDataFetcher::ClearControllers() {
  for (const auto& entry : controllers_)
    entry.second->Shutdown();
  controllers_.clear();
}

void RawInputDataFetcher::GetGamepadData(bool devices_changed_hint) {
  if (!rawinput_available_)
    return;

  if (devices_changed_hint)
    EnumerateDevices();

  for (const auto& entry : controllers_) {
    const RawInputGamepadDeviceWin* device = entry.second.get();
    PadState* state = GetPadState(device->GetSourceId());
    if (!state)
      continue;

    device->ReadPadState(&state->data);
  }
}

void RawInputDataFetcher::EnumerateDevices() {
  UINT count = 0;
  UINT result =
      ::GetRawInputDeviceList(nullptr, &count, sizeof(RAWINPUTDEVICELIST));
  if (result == static_cast<UINT>(-1)) {
    PLOG(ERROR) << "GetRawInputDeviceList() failed";
    return;
  }
  DCHECK_EQ(0u, result);

  std::unique_ptr<RAWINPUTDEVICELIST[]> device_list(
      new RAWINPUTDEVICELIST[count]);
  result = ::GetRawInputDeviceList(device_list.get(), &count,
                                   sizeof(RAWINPUTDEVICELIST));
  if (result == static_cast<UINT>(-1)) {
    PLOG(ERROR) << "GetRawInputDeviceList() failed";
    return;
  }
  DCHECK_EQ(count, result);

  std::unordered_set<HANDLE> enumerated_device_handles;
  for (UINT i = 0; i < count; ++i) {
    if (device_list[i].dwType == RIM_TYPEHID) {
      HANDLE device_handle = device_list[i].hDevice;
      auto controller_it = controllers_.find(device_handle);

      RawInputGamepadDeviceWin* device;
      if (controller_it != controllers_.end()) {
        device = controller_it->second.get();
      } else {
        int source_id = ++last_source_id_;
        auto new_device = std::make_unique<RawInputGamepadDeviceWin>(
            device_handle, source_id, hid_functions_.get());
        if (!new_device->IsValid()) {
          new_device->Shutdown();
          continue;
        }

        // The presence of "IG_" in the device name indicates that this is an
        // XInput Gamepad. Skip enumerating these devices and let the XInput
        // path handle it.
        // http://msdn.microsoft.com/en-us/library/windows/desktop/ee417014.aspx
        const std::wstring device_name = new_device->GetDeviceName();
        if (filter_xinput_ && device_name.find(L"IG_") != std::wstring::npos) {
          new_device->Shutdown();
          continue;
        }

        PadState* state = GetPadState(source_id);
        if (!state) {
          new_device->Shutdown();
          continue;  // No slot available for this gamepad.
        }

        auto emplace_result =
            controllers_.emplace(device_handle, std::move(new_device));
        device = emplace_result.first->second.get();

        Gamepad& pad = state->data;
        pad.connected = true;

        pad.vibration_actuator.type = GamepadHapticActuatorType::kDualRumble;
        pad.vibration_actuator.not_null = device->SupportsVibration();

        const int vendor_int = device->GetVendorId();
        const int product_int = device->GetProductId();
        const int version_number = device->GetVersionNumber();
        const std::wstring product_string = device->GetProductString();

        state->mapper = GetGamepadStandardMappingFunction(
            vendor_int, product_int, version_number, GAMEPAD_BUS_UNKNOWN);
        state->axis_mask = 0;
        state->button_mask = 0;

        swprintf(pad.id, Gamepad::kIdLengthCap,
                 L"%ls (%lsVendor: %04x Product: %04x)", product_string.c_str(),
                 state->mapper ? L"STANDARD GAMEPAD " : L"", vendor_int,
                 product_int);

        if (state->mapper)
          swprintf(pad.mapping, Gamepad::kMappingLengthCap, L"standard");
        else
          pad.mapping[0] = 0;
      }

      enumerated_device_handles.insert(device_handle);
    }
  }

  // Clear out old controllers that weren't part of this enumeration pass.
  auto controller_it = controllers_.begin();
  while (controller_it != controllers_.end()) {
    if (enumerated_device_handles.find(controller_it->first) ==
        enumerated_device_handles.end()) {
      controller_it->second->Shutdown();
      controller_it = controllers_.erase(controller_it);
    } else {
      ++controller_it;
    }
  }
}

RawInputGamepadDeviceWin* RawInputDataFetcher::DeviceFromSourceId(
    int source_id) {
  for (const auto& entry : controllers_) {
    if (entry.second->GetSourceId() == source_id)
      return entry.second.get();
  }
  return nullptr;
}

void RawInputDataFetcher::PlayEffect(
    int source_id,
    mojom::GamepadHapticEffectType type,
    mojom::GamepadEffectParametersPtr params,
    mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback callback,
    scoped_refptr<base::SequencedTaskRunner> callback_runner) {
  RawInputGamepadDeviceWin* device = DeviceFromSourceId(source_id);
  if (!device) {
    RunVibrationCallback(
        std::move(callback), std::move(callback_runner),
        mojom::GamepadHapticsResult::GamepadHapticsResultError);
    return;
  }

  if (!device->SupportsVibration()) {
    RunVibrationCallback(
        std::move(callback), std::move(callback_runner),
        mojom::GamepadHapticsResult::GamepadHapticsResultNotSupported);
    return;
  }

  device->PlayEffect(type, std::move(params), std::move(callback),
                     std::move(callback_runner));
}

void RawInputDataFetcher::ResetVibration(
    int source_id,
    mojom::GamepadHapticsManager::ResetVibrationActuatorCallback callback,
    scoped_refptr<base::SequencedTaskRunner> callback_runner) {
  RawInputGamepadDeviceWin* device = DeviceFromSourceId(source_id);
  if (!device) {
    RunVibrationCallback(
        std::move(callback), std::move(callback_runner),
        mojom::GamepadHapticsResult::GamepadHapticsResultError);
    return;
  }

  if (!device->SupportsVibration()) {
    RunVibrationCallback(
        std::move(callback), std::move(callback_runner),
        mojom::GamepadHapticsResult::GamepadHapticsResultNotSupported);
    return;
  }

  device->ResetVibration(std::move(callback), std::move(callback_runner));
}

LRESULT RawInputDataFetcher::OnInput(HRAWINPUT input_handle) {
  // Get the size of the input record.
  UINT size = 0;
  UINT result = ::GetRawInputData(input_handle, RID_INPUT, nullptr, &size,
                                  sizeof(RAWINPUTHEADER));
  if (result == static_cast<UINT>(-1)) {
    PLOG(ERROR) << "GetRawInputData() failed";
    return 0;
  }
  DCHECK_EQ(0u, result);

  // Retrieve the input record.
  std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]);
  RAWINPUT* input = reinterpret_cast<RAWINPUT*>(buffer.get());
  result = ::GetRawInputData(input_handle, RID_INPUT, buffer.get(), &size,
                             sizeof(RAWINPUTHEADER));
  if (result == static_cast<UINT>(-1)) {
    PLOG(ERROR) << "GetRawInputData() failed";
    return 0;
  }
  DCHECK_EQ(size, result);

  // Notify the observer about events generated locally.
  if (input->header.dwType == RIM_TYPEHID && input->header.hDevice != NULL) {
    auto it = controllers_.find(input->header.hDevice);
    if (it != controllers_.end())
      it->second->UpdateGamepad(input);
  }

  return ::DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER));
}

bool RawInputDataFetcher::HandleMessage(UINT message,
                                        WPARAM wparam,
                                        LPARAM lparam,
                                        LRESULT* result) {
  switch (message) {
    case WM_INPUT:
      *result = OnInput(reinterpret_cast<HRAWINPUT>(lparam));
      return true;

    default:
      return false;
  }
}

}  // namespace device
