// Copyright 2018 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 "service.h"

#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/syslog/cpp/macros.h>

#include <algorithm>
#include <iostream>
#include <iterator>
#include <limits>

using fuchsia::bluetooth::Status;

namespace gatt = fuchsia::bluetooth::gatt;

namespace bt_le_heart_rate {
namespace {

// See Heart Rate Service v1.0, 3.1.1.1 Flags Field
constexpr uint8_t kHeartRateValueFormat = 1 << 0;  // 1 for 16 bit rate value
constexpr uint8_t kSensorContactStatus = 1 << 1;
constexpr uint8_t kSensorContactSupported = 1 << 2;
constexpr uint8_t kEnergyExpendedStatus = 1 << 3;
constexpr uint8_t kRrInterval = 1 << 4;

// Convert an integer type to a smaller integer type with saturation.
template <typename To, typename From>
To Narrow(From value) {
  static_assert(sizeof(To) <= sizeof(From), "Can't narrow to a larger type");

  constexpr From lower_limit = std::numeric_limits<To>::min();
  static_assert(lower_limit >= std::numeric_limits<From>::min(), "Not 1:1");
  constexpr From upper_limit = std::numeric_limits<To>::max();
  static_assert(upper_limit <= std::numeric_limits<From>::max(), "Not 1:1");

  value = std::max(value, lower_limit);
  return static_cast<To>(std::min(value, upper_limit));
}

std::vector<uint8_t> MakeMeasurementPayload(int rate, const bool* sensor_contact,
                                            const int* energy_expended, const int* rr_interval) {
  std::vector<uint8_t> payload(1);

  // Compute width of field necessary for the heart rate.
  // Heart Rate Service v1.0, 3.1.1.1.1: "Heart Rate Value Format bit may change
  // during a connection."
  const uint8_t rate_8bit = Narrow<uint8_t>(rate);
  if (rate_8bit == rate) {
    payload.push_back(rate_8bit);
  } else {
    payload[0] |= kHeartRateValueFormat;
    const auto rate_16bit = Narrow<uint16_t>(rate);
    payload.push_back(static_cast<uint8_t>(rate_16bit));
    payload.push_back(static_cast<uint8_t>(rate_16bit >> 8));
  }

  if (sensor_contact) {
    payload[0] |= kSensorContactSupported;
    payload[0] |= *sensor_contact ? kSensorContactStatus : 0;
  }

  // Heart Rate Service v1.0, 3.1.1.3: "If the maximum value of 65535 kilo
  // Joules is attained (0xFFFF), the field value should remain at 0xFFFF."
  if (energy_expended) {
    payload[0] |= kEnergyExpendedStatus;
    const auto energy_expended_16bit = Narrow<uint16_t>(*energy_expended);
    payload.push_back(static_cast<uint8_t>(energy_expended_16bit));
    payload.push_back(static_cast<uint8_t>(energy_expended_16bit >> 8));
  }

  if (rr_interval) {
    payload[0] |= kRrInterval;
    const auto rr_interval_16bit = Narrow<uint16_t>(*rr_interval);
    payload.push_back(static_cast<uint8_t>(rr_interval_16bit));
    payload.push_back(static_cast<uint8_t>(rr_interval_16bit >> 8));
  }

  return payload;
}

void PrintBytes(const std::vector<uint8_t>& value) {
  const auto fmtflags = std::cout.flags();
  std::cout << std::hex;
  std::copy(value.begin(), value.end(), std::ostream_iterator<unsigned>(std::cout));
  std::cout.flags(fmtflags);
}

}  // namespace

constexpr char Service::kServiceUuid[];
constexpr uint64_t Service::kHeartRateMeasurementId;
constexpr char Service::kHeartRateMeasurementUuid[];
constexpr uint64_t Service::kBodySensorLocationId;
constexpr char Service::kBodySensorLocationUuid[];
constexpr uint64_t Service::kHeartRateControlPointId;
constexpr char Service::kHeartRateControlPointUuid[];

Service::Service(std::unique_ptr<HeartModel> heart_model)
    : heart_model_(std::move(heart_model)),
      binding_(this),
      notify_scheduled_(false),
      weak_factory_(this) {
  FX_DCHECK(heart_model_);
}

void Service::PublishService(gatt::ServerPtr* gatt_server) {
  // Heart Rate Measurement
  // Allow update with default security of "none required."
  gatt::Characteristic hrm;
  hrm.id = kHeartRateMeasurementId;
  hrm.type = kHeartRateMeasurementUuid;
  hrm.properties = gatt::kPropertyNotify;
  hrm.permissions = gatt::AttributePermissions::New();
  hrm.permissions->update = gatt::SecurityRequirements::New();

  // Body Sensor Location
  gatt::Characteristic bsl;
  bsl.id = kBodySensorLocationId;
  bsl.type = kBodySensorLocationUuid;
  bsl.properties = gatt::kPropertyRead;
  bsl.permissions = gatt::AttributePermissions::New();
  bsl.permissions->read = gatt::SecurityRequirements::New();

  // Heart Rate Control Point
  gatt::Characteristic hrcp;
  hrcp.id = kHeartRateControlPointId;
  hrcp.type = kHeartRateControlPointUuid;
  hrcp.properties = gatt::kPropertyWrite;
  hrcp.permissions = gatt::AttributePermissions::New();
  hrcp.permissions->write = gatt::SecurityRequirements::New();

  std::vector<gatt::Characteristic> characteristics;
  characteristics.push_back(std::move(hrm));
  characteristics.push_back(std::move(bsl));
  characteristics.push_back(std::move(hrcp));

  gatt::ServiceInfo si;
  si.primary = true;
  si.type = kServiceUuid;
  si.characteristics = std::move(characteristics);

  std::cout << "Publishing service..." << std::endl;
  auto publish_svc_result_cb = [](Status status) {
    std::cout << "PublishService status: " << bool(status.error) << std::endl;
  };
  (*gatt_server)
      ->PublishService(std::move(si), binding_.NewBinding(), service_.NewRequest(),
                       std::move(publish_svc_result_cb));
}

void Service::NotifyMeasurement() {
  HeartModel::Measurement measurement = {};
  if (!heart_model_->ReadMeasurement(&measurement))
    return;

  const auto payload = MakeMeasurementPayload(measurement.rate, &measurement.contact,
                                              &measurement.energy_expended, nullptr);

  for (const auto& peer_id : measurement_peers_) {
    service_->NotifyValue(0, peer_id, std::move(payload), false);
  }
}

void Service::ScheduleNotification() {
  auto self = weak_factory_.GetWeakPtr();
  async::PostDelayedTask(
      async_get_default_dispatcher(),
      [self] {
        if (!self)
          return;

        if (!self->measurement_peers_.empty()) {
          self->NotifyMeasurement();
          self->ScheduleNotification();
        } else {
          self->notify_scheduled_ = false;
        }
      },
      zx::msec(measurement_interval_));

  notify_scheduled_ = true;
}

void Service::OnCharacteristicConfiguration(uint64_t characteristic_id, std::string peer_id,
                                            bool notify, bool indicate) {
  std::cout << "CharacteristicConfiguration on peer " << peer_id << " (notify: " << notify
            << ", indicate: " << indicate << ")" << std::endl;

  if (characteristic_id != kHeartRateMeasurementId) {
    std::cout << "Ignoring configuration for characteristic other than Heart "
                 "Rate Measurement"
              << std::endl;
    return;
  }

  if (notify) {
    std::cout << "Enabling heart rate measurements for peer " << peer_id << std::endl;

    auto insert_res = measurement_peers_.insert(peer_id);
    if (insert_res.second && measurement_peers_.size() == 1) {
      if (!notify_scheduled_)
        ScheduleNotification();
    }
  } else {
    std::cout << "Disabling heart rate measurements for peer " << peer_id << std::endl;
    measurement_peers_.erase(peer_id);
  }
}

void Service::OnReadValue(uint64_t id, int32_t offset, OnReadValueCallback callback) {
  std::cout << "ReadValue on characteristic " << id << " at offset " << offset << std::endl;

  if (id != kBodySensorLocationId) {
    callback(nullptr, gatt::ErrorCode::NOT_PERMITTED);
    return;
  }

  // Body Sensor Location payload
  std::vector<uint8_t> value;
  value.push_back(static_cast<uint8_t>(BodySensorLocation::kOther));
  callback(std::move(value), gatt::ErrorCode::NO_ERROR);
}

void Service::OnWriteValue(uint64_t id, uint16_t offset, std::vector<uint8_t> value,
                           OnWriteValueCallback callback) {
  std::cout << "WriteValue on characteristic " << id << " at offset " << offset << " (";
  PrintBytes(value);
  std::cout << ")" << std::endl;

  if (id != kHeartRateControlPointId) {
    std::cout << "Ignoring writes to characteristic other than Heart Rate "
                 "Control Point"
              << std::endl;
    callback(gatt::ErrorCode::NOT_PERMITTED);
    return;
  }

  if (offset != 0) {
    std::cout << "Write to control point at invalid offset" << std::endl;
    callback(gatt::ErrorCode::INVALID_OFFSET);
    return;
  }

  if (value.size() != 1) {
    std::cout << "Write to control point of invalid length" << std::endl;
    callback(gatt::ErrorCode::INVALID_VALUE_LENGTH);
    return;
  }

  if (value[0] != kResetEnergyExpendedValue) {
    std::cout << "Write value other than \"Reset Energy Expended\" to "
                 "Heart Rate Control Point characteristic"
              << std::endl;
    callback(CONTROL_POINT_NOT_SUPPORTED);
    return;
  }

  std::cout << "Resetting Energy Expended" << std::endl;
  heart_model_->ResetEnergyExpended();
  callback(gatt::ErrorCode::NO_ERROR);
}

void Service::OnWriteWithoutResponse(uint64_t id, uint16_t offset, std::vector<uint8_t> value) {
  std::cout << "WriteWithoutResponse on characteristic " << id << " at offset " << offset << " (";
  PrintBytes(value);
  std::cout << ")" << std::endl;
}

}  // namespace bt_le_heart_rate
