// 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 "src/ui/lib/input_reader/stylus.h"

#include <fuchsia/ui/input/cpp/fidl.h>

#include <gtest/gtest.h>
#include <hid-parser/parser.h>
#include <hid-parser/usages.h>
#include <hid/acer12.h>
#include <hid/paradise.h>

#include "src/lib/fxl/time/time_point.h"

namespace input {

namespace {
bool usage_is_stylus(hid::Usage usage) {
  using ::hid::usage::Digitizer;
  using ::hid::usage::Page;
  return ((usage == hid::USAGE(Page::kDigitizer, Digitizer::kStylus)) ||
          (usage == hid::USAGE(Page::kDigitizer, Digitizer::kPen)));
}
const hid::ReportDescriptor *get_stylus_descriptor(const hid::DeviceDescriptor *dev_desc) {
  const hid::ReportDescriptor *desc = nullptr;
  for (size_t rep = 0; rep < dev_desc->rep_count; rep++) {
    const hid::ReportDescriptor *tmp_desc = &dev_desc->report[rep];
    // Traverse up the nested collections to the Application collection.
    hid::Collection *collection = tmp_desc->input_fields[0].col;
    while (collection != nullptr) {
      if (collection->type == hid::CollectionType::kApplication) {
        break;
      }
      collection = collection->parent;
    }
    if (!collection) {
      return nullptr;
    }
    if (usage_is_stylus(collection->usage)) {
      desc = tmp_desc;
      break;
    }
  }
  return desc;
}
}  // namespace

// Each test parses the report descriptor for the mouse and then sends one
// report to ensure that it has been parsed correctly.
namespace test {

TEST(StylusTest, Paradise) {
  hid::DeviceDescriptor *dev_desc = nullptr;
  size_t desc_size;
  const uint8_t *paradise_touch_v1_report_desc = get_paradise_touch_report_desc(&desc_size);

  auto parse_res = hid::ParseReportDescriptor(paradise_touch_v1_report_desc, desc_size, &dev_desc);
  ASSERT_EQ(hid::ParseResult::kParseOk, parse_res);

  auto desc = get_stylus_descriptor(dev_desc);
  ASSERT_NE(nullptr, desc);

  ui_input::Stylus stylus = {};
  ui_input::Device::Descriptor device_descriptor = {};
  bool success = stylus.ParseReportDescriptor(*desc, &device_descriptor);
  ASSERT_TRUE(success);
  ASSERT_TRUE(device_descriptor.has_stylus);
  ASSERT_TRUE(device_descriptor.stylus_descriptor != nullptr);

  EXPECT_EQ(0, device_descriptor.stylus_descriptor->x.range.min);
  EXPECT_EQ(25920, device_descriptor.stylus_descriptor->x.range.max);
  EXPECT_EQ(0, device_descriptor.stylus_descriptor->y.range.min);
  EXPECT_EQ(17280, device_descriptor.stylus_descriptor->y.range.max);

  EXPECT_TRUE(device_descriptor.stylus_descriptor->is_invertible);
  EXPECT_EQ(fuchsia::ui::input::kStylusBarrel, device_descriptor.stylus_descriptor->buttons);

  const uint8_t report_data[20] = {
      0x06,        // Report ID
      0xFF,        // Tip switch, barrel switch, eraser, invert, in_range
      0x34, 0x12,  // X
      0x34, 0x12,  // Y
      0x20, 0x00,  // Tip pressure
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  fuchsia::ui::input::InputReport report;
  report.stylus = fuchsia::ui::input::StylusReport::New();
  success = stylus.ParseReport(report_data, sizeof(report_data), &report);
  ASSERT_EQ(true, success);

  // Multiply by a hundred for the unit standardization
  EXPECT_EQ(0x1234 * 100, report.stylus->x);
  EXPECT_EQ(0x1234 * 100, report.stylus->y);
  EXPECT_EQ(0x20U, report.stylus->pressure);
  EXPECT_EQ(true, report.stylus->is_in_contact);
  EXPECT_EQ(true, report.stylus->is_inverted);
  EXPECT_EQ(fuchsia::ui::input::kStylusBarrel, report.stylus->pressed_buttons);
}

TEST(StylusTest, Acer12) {
  hid::DeviceDescriptor *dev_desc = nullptr;
  size_t desc_size;
  const uint8_t *acer12_touch_report_desc = get_acer12_touch_report_desc(&desc_size);

  auto parse_res = hid::ParseReportDescriptor(acer12_touch_report_desc, desc_size, &dev_desc);
  ASSERT_EQ(hid::ParseResult::kParseOk, parse_res);

  auto desc = get_stylus_descriptor(dev_desc);
  ASSERT_NE(nullptr, desc);

  ui_input::Stylus stylus = {};
  ui_input::Device::Descriptor device_descriptor = {};
  bool success = stylus.ParseReportDescriptor(*desc, &device_descriptor);
  ASSERT_TRUE(success);
  ASSERT_TRUE(device_descriptor.has_stylus);
  ASSERT_TRUE(device_descriptor.stylus_descriptor != nullptr);

  EXPECT_EQ(0, device_descriptor.stylus_descriptor->x.range.min);
  EXPECT_EQ(254, device_descriptor.stylus_descriptor->x.range.max);
  EXPECT_EQ(0, device_descriptor.stylus_descriptor->y.range.min);
  EXPECT_EQ(169, device_descriptor.stylus_descriptor->y.range.max);

  EXPECT_TRUE(device_descriptor.stylus_descriptor->is_invertible);
  EXPECT_EQ(fuchsia::ui::input::kStylusBarrel, device_descriptor.stylus_descriptor->buttons);

  const uint8_t report_data[8] = {
      0x07,        // Report ID
      0xFF,        // Tip switch, barrel switch, eraser, invert, in_range
      0x23, 0x01,  // X
      0x23, 0x01,  // Y
      0x20, 0x00,  // Tip pressure
  };

  fuchsia::ui::input::InputReport report;
  report.stylus = fuchsia::ui::input::StylusReport::New();
  success = stylus.ParseReport(report_data, sizeof(report_data), &report);
  ASSERT_EQ(true, success);

  // Manually calculated logical -> physical units
  EXPECT_EQ(183318, report.stylus->x);
  EXPECT_EQ(178702, report.stylus->y);
  EXPECT_EQ(0x20U, report.stylus->pressure);
  EXPECT_EQ(true, report.stylus->is_in_contact);
  EXPECT_EQ(true, report.stylus->is_inverted);
  EXPECT_EQ(fuchsia::ui::input::kStylusBarrel, report.stylus->pressed_buttons);
}

}  // namespace test
}  // namespace input
