// 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/sensor.h"

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

#include <vector>

namespace {

bool IsXUsage(const hid::Usage& u) {
  return (u == hid::USAGE(hid::usage::Page::kSensor,
                          hid::usage::Sensor::kAccelerationAxisX)) ||
         (u == hid::USAGE(hid::usage::Page::kSensor,
                          hid::usage::Sensor::kDistanceAxisX)) ||
         (u == hid::USAGE(hid::usage::Page::kSensor,
                          hid::usage::Sensor::kTiltAxisX)) ||
         (u == hid::USAGE(hid::usage::Page::kSensor,
                          hid::usage::Sensor::kMagneticFluxAxisX));
}

bool IsYUsage(const hid::Usage& u) {
  return (u == hid::USAGE(hid::usage::Page::kSensor,
                          hid::usage::Sensor::kAccelerationAxisY)) ||
         (u == hid::USAGE(hid::usage::Page::kSensor,
                          hid::usage::Sensor::kDistanceAxisY)) ||
         (u == hid::USAGE(hid::usage::Page::kSensor,
                          hid::usage::Sensor::kTiltAxisY)) ||
         (u == hid::USAGE(hid::usage::Page::kSensor,
                          hid::usage::Sensor::kMagneticFluxAxisY));
}

bool IsZUsage(const hid::Usage& u) {
  return (u == hid::USAGE(hid::usage::Page::kSensor,
                          hid::usage::Sensor::kAccelerationAxisZ)) ||
         (u == hid::USAGE(hid::usage::Page::kSensor,
                          hid::usage::Sensor::kDistanceAxisZ)) ||
         (u == hid::USAGE(hid::usage::Page::kSensor,
                          hid::usage::Sensor::kTiltAxisZ)) ||
         (u == hid::USAGE(hid::usage::Page::kSensor,
                          hid::usage::Sensor::kMagneticFluxAxisZ));
}

}  // namespace

namespace ui_input {

bool Sensor::ParseReportDescriptor(
    const hid::ReportDescriptor& report_descriptor,
    Descriptor* device_descriptor) {
  FXL_CHECK(device_descriptor);

  fuchsia::ui::input::SensorType sensor_type;
  hid::Attributes x = {};
  hid::Attributes y = {};
  hid::Attributes z = {};
  hid::Attributes scalar = {};
  uint32_t caps = 0;

  auto sensor_usage = report_descriptor.input_fields[0].col->usage;
  if (sensor_usage == hid::USAGE(hid::usage::Page::kSensor,
                                 hid::usage::Sensor::kAccelerometer3D)) {
    sensor_type = fuchsia::ui::input::SensorType::ACCELEROMETER;

  } else if (sensor_usage == hid::USAGE(hid::usage::Page::kSensor,
                                        hid::usage::Sensor::kGyrometer3D)) {
    sensor_type = fuchsia::ui::input::SensorType::GYROSCOPE;

  } else if (sensor_usage == hid::USAGE(hid::usage::Page::kSensor,
                                        hid::usage::Sensor::kMagnetometer)) {
    sensor_type = fuchsia::ui::input::SensorType::MAGNETOMETER;

  } else if (sensor_usage == hid::USAGE(hid::usage::Page::kSensor,
                                        hid::usage::Sensor::kAmbientLight)) {
    sensor_type = fuchsia::ui::input::SensorType::LIGHTMETER;

  } else {
    FXL_LOG(INFO) << "Sensor report descriptor: Sensor page not supported (0x"
                  << std::hex << sensor_usage.usage << ")";
    return false;
  }

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

    if (IsXUsage(field.attr.usage)) {
      x = field.attr;
      caps |= Capabilities::X;
    } else if (IsYUsage(field.attr.usage)) {
      y = field.attr;
      caps |= Capabilities::Y;
    } else if (IsZUsage(field.attr.usage)) {
      z = field.attr;
      caps |= Capabilities::Z;
    } else {
      // At this point, any non X, Y, Z fields in a sensor are put into
      // scalar. InputReport only supports a single scalar so we will
      // pick the last value we see.
      scalar = field.attr;
      caps |= Capabilities::SCALAR;
    }
  }

  if ((caps & Capabilities::SCALAR) &&
      (caps & (Capabilities::X | Capabilities::Y | Capabilities::Z))) {
    FXL_LOG(INFO) << "Sensor report descriptor: Sensor describes Axis and "
                     "Scalar, must only describe one";
    return false;
  }

  if (caps == 0) {
    FXL_LOG(INFO) << "Sensor report descriptor: Sensor has no capabilities";
    return false;
  }

  // TODO(SCN-1312): In order to get min sampling rate, max sampling rate,
  // phys_min, and phys_max, we will need to see example reports of how these
  // things are set. This is currently not supported by the hardcoded sensors
  // either.

  x_ = x;
  y_ = y;
  z_ = z;
  scalar_ = scalar;
  capabilities_ = caps;

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

  // Set the device descriptor.
  device_descriptor->protocol = Protocol::Sensor;
  device_descriptor->has_sensor = true;
  device_descriptor->sensor_descriptor =
      fuchsia::ui::input::SensorDescriptor::New();
  device_descriptor->sensor_descriptor->type = sensor_type;
  return true;
}

bool Sensor::ParseReport(const uint8_t* data, size_t len,
                         fuchsia::ui::input::InputReport* report) {
  FXL_CHECK(report);
  FXL_CHECK(report->sensor);
  double x = 0;
  double y = 0;
  double z = 0;
  double scalar = 0;

  if (report_size_ != len) {
    FXL_LOG(INFO) << "Sensor report: Expected size " << report_size_
                  << "Recieved size " << len;
    return false;
  }

  if (capabilities_ & Capabilities::X) {
    if (!hid::ExtractAsUnit(data, len, x_, &x)) {
      FXL_LOG(INFO) << "Sensor report: Failed to parse X";
      return false;
    }
  }
  if (capabilities_ & Capabilities::Y) {
    if (!hid::ExtractAsUnit(data, len, y_, &y)) {
      FXL_LOG(INFO) << "Sensor report: Failed to parse Y";
      return false;
    }
  }
  if (capabilities_ & Capabilities::Z) {
    if (!hid::ExtractAsUnit(data, len, z_, &z)) {
      FXL_LOG(INFO) << "Sensor report: Failed to parse Z";
      return false;
    }
  }
  if (capabilities_ & Capabilities::SCALAR) {
    if (!hid::ExtractAsUnit(data, len, scalar_, &scalar)) {
      FXL_LOG(INFO) << "Sensor report: Failed to parse Scalar";
      return false;
    }
  }

  FXL_DCHECK(x >= INT16_MIN && x <= INT16_MAX)
      << "X sensor value is truncated.";
  FXL_DCHECK(y >= INT16_MIN && y <= INT16_MAX)
      << "Y sensor value is truncated.";
  FXL_DCHECK(z >= INT16_MIN && z <= INT16_MAX)
      << "Z sensor value is truncated.";

  if (capabilities_ & (Capabilities::X | Capabilities::Y | Capabilities::Z)) {
    std::array<int16_t, 3> axis;
    axis[0] = x;
    axis[1] = y;
    axis[2] = z;
    report->sensor->set_vector(std::move(axis));
  } else if (capabilities_ & Capabilities::SCALAR) {
    report->sensor->set_scalar(scalar);
  }

  return true;
}

}  // namespace ui_input
