// Copyright 2019 The Fuchsia 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 "garnet/bin/ui/input_reader/mouse.h"
#include "garnet/bin/ui/input_reader/device.h"

#include <hid-parser/parser.h>
#include <hid-parser/report.h>
#include <hid-parser/units.h>
#include <hid-parser/usages.h>

#include <stdint.h>
#include <stdio.h>
#include <vector>

#include <src/lib/fxl/logging.h>

namespace mozart {

bool Mouse::ParseReportDescriptor(
    const hid::ReportDescriptor& report_descriptor,
    Descriptor* device_descriptor) {
  hid::Attributes left_click = {};
  hid::Attributes middle_click = {};
  hid::Attributes right_click = {};
  hid::Attributes x = {};
  hid::Attributes y = {};
  uint32_t caps = 0;

  for (size_t i = 0; i < report_descriptor.input_count; i++) {
    const hid::ReportField& field = report_descriptor.input_fields[i];

    if (field.attr.usage == hid::USAGE(hid::usage::Page::kButton, 1)) {
      left_click = field.attr;
      caps |= Capabilities::LEFT_CLICK;

    } else if (field.attr.usage == hid::USAGE(hid::usage::Page::kButton, 2)) {
      middle_click = field.attr;
      caps |= Capabilities::MIDDLE_CLICK;

    } else if (field.attr.usage == hid::USAGE(hid::usage::Page::kButton, 3)) {
      right_click = field.attr;
      caps |= Capabilities::RIGHT_CLICK;

    } else if (field.attr.usage == hid::USAGE(hid::usage::Page::kGenericDesktop,
                                              hid::usage::GenericDesktop::kX)) {
      x = field.attr;
      caps |= Capabilities::X;

    } else if (field.attr.usage == hid::USAGE(hid::usage::Page::kGenericDesktop,
                                              hid::usage::GenericDesktop::kY)) {
      y = field.attr;
      caps |= Capabilities::Y;
    }
  }

  uint32_t base_caps =
      (Capabilities::X | Capabilities::Y | Capabilities::LEFT_CLICK);
  if ((caps & base_caps) != base_caps) {
    FXL_LOG(INFO) << "Mouse descriptor: Missing basic capabilities";
    return false;
  }

  // No error, write to class members.
  left_click_ = left_click;
  middle_click_ = middle_click;
  right_click_ = right_click;
  x_ = x;
  y_ = y;
  capabilities_ = caps;

  report_size_ = report_descriptor.input_byte_sz;
  report_id_ = report_descriptor.report_id;

  // Set the device descriptor.
  device_descriptor->protocol = Protocol::Mouse;
  device_descriptor->has_mouse = true;
  device_descriptor->mouse_type = MouseDeviceType::HID;
  device_descriptor->mouse_descriptor =
      fuchsia::ui::input::MouseDescriptor::New();
  // At the moment all mice send relative units, so these min and max values
  // do not affect anything. Set them to maximum range.
  device_descriptor->mouse_descriptor->rel_x.range.min = INT32_MIN;
  device_descriptor->mouse_descriptor->rel_x.range.max = INT32_MAX;
  device_descriptor->mouse_descriptor->rel_x.resolution = 1;

  device_descriptor->mouse_descriptor->rel_y.range.min = INT32_MIN;
  device_descriptor->mouse_descriptor->rel_y.range.max = INT32_MAX;
  device_descriptor->mouse_descriptor->rel_y.resolution = 1;

  device_descriptor->mouse_descriptor->buttons |=
      fuchsia::ui::input::kMouseButtonPrimary;
  device_descriptor->mouse_descriptor->buttons |=
      fuchsia::ui::input::kMouseButtonSecondary;
  device_descriptor->mouse_descriptor->buttons |=
      fuchsia::ui::input::kMouseButtonTertiary;

  return true;
}

bool Mouse::ParseReport(const uint8_t* data, size_t len,
                        fuchsia::ui::input::InputReport* report) {
  FXL_CHECK(report);
  FXL_CHECK(report->mouse);

  if (data[0] != report_id_) {
    FXL_VLOG(0) << " Mouse report " << static_cast<uint32_t>(data[0])
                << " does not match report id "
                << static_cast<uint32_t>(report_id_);
  }

  Report mouse_report = {};
  if (len != report_size_) {
    FXL_LOG(INFO) << "Mouse HID Report is not correct size, (" << len
                   << " != " << report_size_ << ")";
    return false;
  }

  uint32_t clicked;
  if (capabilities_ & Capabilities::LEFT_CLICK) {
    if (!hid::ExtractUint(data, len, left_click_, &clicked)) {
      FXL_LOG(INFO) << "Mouse report: Failed to parse LEFT_CLICK";
      return false;
    }
    mouse_report.left_click = (clicked == 1);
  }
  if (capabilities_ & Capabilities::MIDDLE_CLICK) {
    if (!hid::ExtractUint(data, len, middle_click_, &clicked)) {
      FXL_LOG(INFO) << "Mouse report: Failed to parse MIDDLE_CLICK";
      return false;
    }
    mouse_report.middle_click = (clicked == 1);
  }
  if (capabilities_ & Capabilities::RIGHT_CLICK) {
    if (!hid::ExtractUint(data, len, right_click_, &clicked)) {
      FXL_LOG(INFO) << "Mouse report: Failed to parse RIGHT_CLICK";
      return false;
    }
    mouse_report.right_click = (clicked == 1);
  }

  // rel_x and rel_y will have units of 10^-5 meters if the report defines units
  hid::Unit length_unit = {};
  length_unit.exp = -5;
  hid::unit::SetSystem(length_unit, hid::unit::System::si_linear);
  hid::unit::SetLengthExp(length_unit, 1);

  if (capabilities_ & Capabilities::X) {
    double x;
    if (!hid::ExtractAsUnit(data, len, x_, &x)) {
      FXL_LOG(INFO) << "Mouse report: Failed to parse X";
      return false;
    }

    // If this returns true, scan_time was converted. If it returns false,
    // scan_time is unchanged. Either way we return successfully.
    hid::unit::ConvertUnits(x_.unit, x, length_unit, &x);

    mouse_report.rel_x = static_cast<int32_t>(x);
  }
  if (capabilities_ & Capabilities::Y) {
    double y;
    if (!hid::ExtractAsUnit(data, len, y_, &y)) {
      FXL_LOG(INFO) << "Mouse report: Failed to parse Y";
      return false;
    }

    // If this returns true, scan_time was converted. If it returns false,
    // scan_time is unchanged. Either way we return successfully.
    hid::unit::ConvertUnits(y_.unit, y, length_unit, &y);

    mouse_report.rel_y = static_cast<int32_t>(y);
  }

  // Now that we can't fail, set the real report.
  report->mouse->rel_x = mouse_report.rel_x;
  report->mouse->rel_y = mouse_report.rel_y;

  report->mouse->pressed_buttons = 0;
  report->mouse->pressed_buttons |=
      mouse_report.left_click ? fuchsia::ui::input::kMouseButtonPrimary : 0;
  report->mouse->pressed_buttons |=
      mouse_report.middle_click ? fuchsia::ui::input::kMouseButtonSecondary : 0;
  report->mouse->pressed_buttons |=
      mouse_report.right_click ? fuchsia::ui::input::kMouseButtonTertiary : 0;

  return true;
}

}  // namespace mozart
