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

        const std::string vendor = base::StringPrintf("%04x", vendor_int);
        const std::string product = base::StringPrintf("%04x", product_int);
        const std::string version = base::StringPrintf("%04x", version_number);
        state->mapper = GetGamepadStandardMappingFunction(
            vendor, product, version, 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) {
  RawInputGamepadDeviceWin* device = DeviceFromSourceId(source_id);
  if (!device) {
    std::move(callback).Run(
        mojom::GamepadHapticsResult::GamepadHapticsResultError);
    return;
  }

  if (!device->SupportsVibration()) {
    std::move(callback).Run(
        mojom::GamepadHapticsResult::GamepadHapticsResultNotSupported);
    return;
  }

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

void RawInputDataFetcher::ResetVibration(
    int source_id,
    mojom::GamepadHapticsManager::ResetVibrationActuatorCallback callback) {
  RawInputGamepadDeviceWin* device = DeviceFromSourceId(source_id);
  if (!device) {
    std::move(callback).Run(
        mojom::GamepadHapticsResult::GamepadHapticsResultError);
    return;
  }

  if (!device->SupportsVibration()) {
    std::move(callback).Run(
        mojom::GamepadHapticsResult::GamepadHapticsResultNotSupported);
    return;
  }

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

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
