// 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 <stdint.h>
#include <stdio.h>

#include <vector>

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

#include "src/lib/fxl/logging.h"
#include "src/ui/lib/input_reader/device.h"

namespace ui_input {

bool Stylus::ParseReportDescriptor(const hid::ReportDescriptor& report_descriptor,
                                   Descriptor* device_descriptor) {
  hid::Attributes x = {};
  hid::Attributes y = {};
  hid::Attributes pressure = {};
  hid::Attributes tip_switch = {};
  hid::Attributes barrel_switch = {};
  hid::Attributes invert = {};
  hid::Attributes eraser = {};
  hid::Attributes in_range = {};
  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::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;
    } else if (field.attr.usage ==
               hid::USAGE(hid::usage::Page::kDigitizer, hid::usage::Digitizer::kTipPressure)) {
      pressure = field.attr;
      caps |= Capabilities::PRESSURE;
    } else if (field.attr.usage ==
               hid::USAGE(hid::usage::Page::kDigitizer, hid::usage::Digitizer::kBarrelSwitch)) {
      barrel_switch = field.attr;
      caps |= Capabilities::BARREL_SWITCH;
    } else if (field.attr.usage ==
               hid::USAGE(hid::usage::Page::kDigitizer, hid::usage::Digitizer::kInvert)) {
      invert = field.attr;
      caps |= Capabilities::INVERT;
    } else if (field.attr.usage ==
               hid::USAGE(hid::usage::Page::kDigitizer, hid::usage::Digitizer::kEraser)) {
      eraser = field.attr;
      caps |= Capabilities::ERASER;
    } else if (field.attr.usage ==
               hid::USAGE(hid::usage::Page::kDigitizer, hid::usage::Digitizer::kInRange)) {
      in_range = field.attr;
      caps |= Capabilities::IN_RANGE;
    }
  }

  // No error, write to class members.
  x_ = x;
  y_ = y;
  pressure_ = pressure;
  tip_switch_ = tip_switch;
  barrel_switch_ = barrel_switch;
  invert_ = invert;
  eraser_ = eraser;
  in_range_ = in_range;
  capabilities_ = caps;

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

  device_descriptor->protocol = Protocol::Stylus;
  device_descriptor->has_stylus = true;
  device_descriptor->stylus_descriptor = fuchsia::ui::input::StylusDescriptor::New();

  device_descriptor->stylus_descriptor->x.range.min = x_.phys_mm.min;
  device_descriptor->stylus_descriptor->x.range.max = x_.phys_mm.max;
  device_descriptor->stylus_descriptor->x.resolution = 1;

  device_descriptor->stylus_descriptor->y.range.min = y_.phys_mm.min;
  device_descriptor->stylus_descriptor->y.range.max = y_.phys_mm.max;
  device_descriptor->stylus_descriptor->y.resolution = 1;

  device_descriptor->stylus_descriptor->is_invertible =
      ((capabilities_ & Capabilities::INVERT) != 0);

  device_descriptor->stylus_descriptor->buttons = 0;
  if (capabilities_ & Capabilities::BARREL_SWITCH) {
    device_descriptor->stylus_descriptor->buttons |= fuchsia::ui::input::kStylusBarrel;
  }

  return true;
}

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

  double x = 0;
  double y = 0;
  double pressure = 0;
  bool tip_switch = false;
  bool barrel_switch = false;
  bool invert = false;
  bool eraser = false;
  bool in_range = false;
  uint8_t tmp_val;

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

  // 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) {
    if (!hid::ExtractAsUnit(data, len, x_, &x)) {
      FXL_LOG(INFO) << "Stylus 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);
  }
  if (capabilities_ & Capabilities::Y) {
    if (!hid::ExtractAsUnit(data, len, y_, &y)) {
      FXL_LOG(INFO) << "Stylus 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);
  }
  if (capabilities_ & Capabilities::PRESSURE) {
    if (!hid::ExtractAsUnit(data, len, pressure_, &pressure)) {
      FXL_LOG(INFO) << "Stylus report: Failed to parse PRESSURE";
      return false;
    }
  }
  if (capabilities_ & Capabilities::TIP_SWITCH) {
    if (!hid::ExtractUint(data, len, tip_switch_, &tmp_val)) {
      FXL_LOG(INFO) << "Stylus report: Failed to parse TIP_SWITCH";
      return false;
    }
    tip_switch = (tmp_val == 1);
  }
  if (capabilities_ & Capabilities::BARREL_SWITCH) {
    if (!hid::ExtractUint(data, len, barrel_switch_, &tmp_val)) {
      FXL_LOG(INFO) << "Stylus report: Failed to parse BARREL_SWITCH";
      return false;
    }
    barrel_switch = (tmp_val == 1);
  }
  if (capabilities_ & Capabilities::INVERT) {
    if (!hid::ExtractUint(data, len, invert_, &tmp_val)) {
      FXL_LOG(INFO) << "Stylus report: Failed to parse INVERT";
      return false;
    }
    invert = (tmp_val == 1);
  }
  if (capabilities_ & Capabilities::ERASER) {
    if (!hid::ExtractUint(data, len, eraser_, &tmp_val)) {
      FXL_LOG(INFO) << "Stylus report: Failed to parse ERASER";
      return false;
    }
    eraser = (tmp_val == 1);
  }
  if (capabilities_ & Capabilities::IN_RANGE) {
    if (!hid::ExtractUint(data, len, in_range_, &tmp_val)) {
      FXL_LOG(INFO) << "Stylus report: Failed to parse IN_RANGE";
      return false;
    }
    in_range = (tmp_val == 1);
  }

  // Now that we can't fail, set the real report.
  report->stylus->x = x;
  report->stylus->y = y;
  report->stylus->pressure = pressure;
  report->stylus->is_in_contact = in_range && (tip_switch || eraser);
  report->stylus->is_inverted = invert;
  if (barrel_switch) {
    report->stylus->pressed_buttons |= fuchsia::ui::input::kStylusBarrel;
  }

  return true;
}

}  // namespace ui_input
