// Copyright 2014 The Chromium 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 "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h"

#include "base/bind.h"
#include "base/location.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace bluez {

namespace {

const int kStartNotifyResponseIntervalMs = 200;
const int kHeartRateMeasurementNotificationIntervalMs = 2000;

}  // namespace

FakeBluetoothGattCharacteristicClient::DelayedCallback::DelayedCallback(
    base::Closure callback,
    size_t delay)
    : callback_(callback), delay_(delay) {}

FakeBluetoothGattCharacteristicClient::DelayedCallback::~DelayedCallback() =
    default;

// static
const char FakeBluetoothGattCharacteristicClient::
    kHeartRateMeasurementPathComponent[] = "char0000";
const char
    FakeBluetoothGattCharacteristicClient::kBodySensorLocationPathComponent[] =
        "char0001";
const char FakeBluetoothGattCharacteristicClient::
    kHeartRateControlPointPathComponent[] = "char0002";

// static
const char FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID[] =
    "00002a37-0000-1000-8000-00805f9b34fb";
const char FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID[] =
    "00002a38-0000-1000-8000-00805f9b34fb";
const char FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID[] =
    "00002a39-0000-1000-8000-00805f9b34fb";

FakeBluetoothGattCharacteristicClient::Properties::Properties(
    const PropertyChangedCallback& callback)
    : BluetoothGattCharacteristicClient::Properties(
          NULL,
          bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface,
          callback) {}

FakeBluetoothGattCharacteristicClient::Properties::~Properties() = default;

void FakeBluetoothGattCharacteristicClient::Properties::Get(
    dbus::PropertyBase* property,
    dbus::PropertySet::GetCallback callback) {
  VLOG(1) << "Get " << property->name();
  callback.Run(true);
}

void FakeBluetoothGattCharacteristicClient::Properties::GetAll() {
  VLOG(1) << "GetAll";
}

void FakeBluetoothGattCharacteristicClient::Properties::Set(
    dbus::PropertyBase* property,
    dbus::PropertySet::SetCallback callback) {
  VLOG(1) << "Set " << property->name();
  callback.Run(false);
}

FakeBluetoothGattCharacteristicClient::FakeBluetoothGattCharacteristicClient()
    : heart_rate_visible_(false),
      authorized_(true),
      authenticated_(true),
      calories_burned_(0),
      extra_requests_(0),
      weak_ptr_factory_(this) {}

FakeBluetoothGattCharacteristicClient::
    ~FakeBluetoothGattCharacteristicClient() {
  for (const auto& it : action_extra_requests_) {
    delete it.second;
  }
  action_extra_requests_.clear();
}

void FakeBluetoothGattCharacteristicClient::Init(
    dbus::Bus* bus,
    const std::string& bluetooth_service_name) {}

void FakeBluetoothGattCharacteristicClient::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void FakeBluetoothGattCharacteristicClient::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

std::vector<dbus::ObjectPath>
FakeBluetoothGattCharacteristicClient::GetCharacteristics() {
  std::vector<dbus::ObjectPath> paths;
  if (IsHeartRateVisible()) {
    paths.push_back(dbus::ObjectPath(heart_rate_measurement_path_));
    paths.push_back(dbus::ObjectPath(body_sensor_location_path_));
    paths.push_back(dbus::ObjectPath(heart_rate_control_point_path_));
  }
  return paths;
}

FakeBluetoothGattCharacteristicClient::Properties*
FakeBluetoothGattCharacteristicClient::GetProperties(
    const dbus::ObjectPath& object_path) {
  if (object_path.value() == heart_rate_measurement_path_) {
    DCHECK(heart_rate_measurement_properties_.get());
    return heart_rate_measurement_properties_.get();
  }
  if (object_path.value() == body_sensor_location_path_) {
    DCHECK(body_sensor_location_properties_.get());
    return body_sensor_location_properties_.get();
  }
  if (object_path.value() == heart_rate_control_point_path_) {
    DCHECK(heart_rate_control_point_properties_.get());
    return heart_rate_control_point_properties_.get();
  }
  return NULL;
}

void FakeBluetoothGattCharacteristicClient::ReadValue(
    const dbus::ObjectPath& object_path,
    const ValueCallback& callback,
    const ErrorCallback& error_callback) {
  if (!authenticated_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotPaired, "Please login");
    return;
  }

  if (!authorized_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotAuthorized,
                       "Authorize first");
    return;
  }

  if (object_path.value() == heart_rate_control_point_path_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotPermitted,
                       "Reads of this value are not allowed");
    return;
  }

  if (object_path.value() == heart_rate_measurement_path_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotSupported,
                       "Action not supported on this characteristic");
    return;
  }

  if (object_path.value() != body_sensor_location_path_) {
    error_callback.Run(kUnknownCharacteristicError, "");
    return;
  }

  if (action_extra_requests_.find("ReadValue") !=
      action_extra_requests_.end()) {
    DelayedCallback* delayed = action_extra_requests_["ReadValue"];
    delayed->delay_--;
    error_callback.Run(bluetooth_gatt_service::kErrorInProgress,
                       "Another read is currenty in progress");
    if (delayed->delay_ == 0) {
      delayed->callback_.Run();
      action_extra_requests_.erase("ReadValue");
      delete delayed;
    }
    return;
  }

  base::Closure completed_callback;
  if (!IsHeartRateVisible()) {
    completed_callback =
        base::Bind(error_callback, kUnknownCharacteristicError, "");
  } else {
    std::vector<uint8_t> value = {0x06};  // Location is "foot".
    completed_callback = base::Bind(
        &FakeBluetoothGattCharacteristicClient::DelayedReadValueCallback,
        weak_ptr_factory_.GetWeakPtr(), object_path, callback, value);
  }

  if (extra_requests_ > 0) {
    action_extra_requests_["ReadValue"] =
        new DelayedCallback(completed_callback, extra_requests_);
    return;
  }

  completed_callback.Run();
}

void FakeBluetoothGattCharacteristicClient::WriteValue(
    const dbus::ObjectPath& object_path,
    const std::vector<uint8_t>& value,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  if (!authenticated_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotPaired, "Please login");
    return;
  }

  if (!authorized_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotAuthorized,
                       "Authorize first");
    return;
  }

  if (!IsHeartRateVisible()) {
    error_callback.Run(kUnknownCharacteristicError, "");
    return;
  }

  if (object_path.value() == heart_rate_measurement_path_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotSupported,
                       "Action not supported on this characteristic");
    return;
  }

  if (object_path.value() != heart_rate_control_point_path_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotPermitted,
                       "Writes of this value are not allowed");
    return;
  }

  DCHECK(heart_rate_control_point_properties_.get());
  if (action_extra_requests_.find("WriteValue") !=
      action_extra_requests_.end()) {
    DelayedCallback* delayed = action_extra_requests_["WriteValue"];
    delayed->delay_--;
    error_callback.Run(bluetooth_gatt_service::kErrorInProgress,
                       "Another write is in progress");
    if (delayed->delay_ == 0) {
      delayed->callback_.Run();
      action_extra_requests_.erase("WriteValue");
      delete delayed;
    }
    return;
  }
  base::Closure completed_callback;
  if (value.size() != 1) {
    completed_callback = base::Bind(
        error_callback, bluetooth_gatt_service::kErrorInvalidValueLength,
        "Invalid length for write");
  } else if (value[0] > 1) {
    completed_callback =
        base::Bind(error_callback, bluetooth_gatt_service::kErrorFailed,
                   "Invalid value given for write");
  } else if (value[0] == 1) {
    // TODO(jamuraa): make this happen when the callback happens
    calories_burned_ = 0;
    ScheduleHeartRateMeasurementValueChange();
    completed_callback = callback;
  }

  if (extra_requests_ > 0) {
    action_extra_requests_["WriteValue"] =
        new DelayedCallback(completed_callback, extra_requests_);
    return;
  }
  completed_callback.Run();
}

void FakeBluetoothGattCharacteristicClient::PrepareWriteValue(
    const dbus::ObjectPath& object_path,
    const std::vector<uint8_t>& value,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  if (!authenticated_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotPaired, "Please login");
    return;
  }

  if (!authorized_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotAuthorized,
                       "Authorize first");
    return;
  }

  if (!IsHeartRateVisible()) {
    error_callback.Run(kUnknownCharacteristicError, "");
    return;
  }

  if (object_path.value() == heart_rate_measurement_path_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotSupported,
                       "Action not supported on this characteristic");
    return;
  }

  if (object_path.value() != heart_rate_control_point_path_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotPermitted,
                       "Writes of this value are not allowed");
    return;
  }

  DCHECK(heart_rate_control_point_properties_.get());
  static_cast<FakeBluetoothDeviceClient*>(
      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient())
      ->AddPrepareWriteRequest(object_path, value);
  callback.Run();
}

void FakeBluetoothGattCharacteristicClient::StartNotify(
    const dbus::ObjectPath& object_path,
#if defined(OS_CHROMEOS)
    device::BluetoothGattCharacteristic::NotificationType notification_type,
#endif
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  if (!IsHeartRateVisible()) {
    error_callback.Run(kUnknownCharacteristicError, "");
    return;
  }

  if (object_path.value() != heart_rate_measurement_path_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotSupported,
                       "This characteristic does not support notifications");
    return;
  }

  if (heart_rate_measurement_properties_->notifying.value()) {
    error_callback.Run(bluetooth_gatt_service::kErrorInProgress,
                       "Characteristic already notifying");
    return;
  }

  heart_rate_measurement_properties_->notifying.ReplaceValue(true);
  ScheduleHeartRateMeasurementValueChange();

  // Respond asynchronously.
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE, callback,
      base::TimeDelta::FromMilliseconds(kStartNotifyResponseIntervalMs));
}

void FakeBluetoothGattCharacteristicClient::StopNotify(
    const dbus::ObjectPath& object_path,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  if (!IsHeartRateVisible()) {
    error_callback.Run(kUnknownCharacteristicError, "");
    return;
  }

  if (object_path.value() != heart_rate_measurement_path_) {
    error_callback.Run(bluetooth_gatt_service::kErrorNotSupported,
                       "This characteristic does not support notifications");
    return;
  }

  if (!heart_rate_measurement_properties_->notifying.value()) {
    error_callback.Run(bluetooth_gatt_service::kErrorFailed, "Not notifying");
    return;
  }

  heart_rate_measurement_properties_->notifying.ReplaceValue(false);

  callback.Run();
}

void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics(
    const dbus::ObjectPath& service_path) {
  if (IsHeartRateVisible()) {
    VLOG(2) << "Fake Heart Rate characteristics are already visible.";
    return;
  }

  VLOG(2) << "Exposing fake Heart Rate characteristics.";

  std::vector<std::string> flags;

  // ==== Heart Rate Measurement Characteristic ====
  heart_rate_measurement_path_ =
      service_path.value() + "/" + kHeartRateMeasurementPathComponent;
  heart_rate_measurement_properties_.reset(new Properties(
      base::Bind(&FakeBluetoothGattCharacteristicClient::OnPropertyChanged,
                 weak_ptr_factory_.GetWeakPtr(),
                 dbus::ObjectPath(heart_rate_measurement_path_))));
  heart_rate_measurement_properties_->uuid.ReplaceValue(
      kHeartRateMeasurementUUID);
  heart_rate_measurement_properties_->service.ReplaceValue(service_path);
  flags.push_back(bluetooth_gatt_characteristic::kFlagNotify);
  flags.push_back(bluetooth_gatt_characteristic::kFlagIndicate);
  heart_rate_measurement_properties_->flags.ReplaceValue(flags);

  // ==== Body Sensor Location Characteristic ====
  body_sensor_location_path_ =
      service_path.value() + "/" + kBodySensorLocationPathComponent;
  body_sensor_location_properties_.reset(new Properties(
      base::Bind(&FakeBluetoothGattCharacteristicClient::OnPropertyChanged,
                 weak_ptr_factory_.GetWeakPtr(),
                 dbus::ObjectPath(body_sensor_location_path_))));
  body_sensor_location_properties_->uuid.ReplaceValue(kBodySensorLocationUUID);
  body_sensor_location_properties_->service.ReplaceValue(service_path);
  flags.clear();
  flags.push_back(bluetooth_gatt_characteristic::kFlagRead);
  body_sensor_location_properties_->flags.ReplaceValue(flags);

  // ==== Heart Rate Control Point Characteristic ====
  heart_rate_control_point_path_ =
      service_path.value() + "/" + kHeartRateControlPointPathComponent;
  heart_rate_control_point_properties_.reset(new Properties(
      base::Bind(&FakeBluetoothGattCharacteristicClient::OnPropertyChanged,
                 weak_ptr_factory_.GetWeakPtr(),
                 dbus::ObjectPath(heart_rate_control_point_path_))));
  heart_rate_control_point_properties_->uuid.ReplaceValue(
      kHeartRateControlPointUUID);
  heart_rate_control_point_properties_->service.ReplaceValue(service_path);
  flags.clear();
  flags.push_back(bluetooth_gatt_characteristic::kFlagWrite);
  heart_rate_control_point_properties_->flags.ReplaceValue(flags);

  heart_rate_visible_ = true;

  NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_measurement_path_));
  NotifyCharacteristicAdded(dbus::ObjectPath(body_sensor_location_path_));
  NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_control_point_path_));

  // Expose CCC descriptor for Heart Rate Measurement characteristic.
  FakeBluetoothGattDescriptorClient* descriptor_client =
      static_cast<FakeBluetoothGattDescriptorClient*>(
          bluez::BluezDBusManager::Get()->GetBluetoothGattDescriptorClient());
  dbus::ObjectPath ccc_path(descriptor_client->ExposeDescriptor(
      dbus::ObjectPath(heart_rate_measurement_path_),
      FakeBluetoothGattDescriptorClient::
          kClientCharacteristicConfigurationUUID));
  DCHECK(ccc_path.IsValid());
  heart_rate_measurement_ccc_desc_path_ = ccc_path.value();
}

void FakeBluetoothGattCharacteristicClient::HideHeartRateCharacteristics() {
  VLOG(2) << "Hiding fake Heart Rate characteristics.";

  // Hide the descriptors.
  FakeBluetoothGattDescriptorClient* descriptor_client =
      static_cast<FakeBluetoothGattDescriptorClient*>(
          bluez::BluezDBusManager::Get()->GetBluetoothGattDescriptorClient());
  descriptor_client->HideDescriptor(
      dbus::ObjectPath(heart_rate_measurement_ccc_desc_path_));

  // Notify the observers before deleting the properties structures so that they
  // can be accessed from the observer method.
  NotifyCharacteristicRemoved(dbus::ObjectPath(heart_rate_measurement_path_));
  NotifyCharacteristicRemoved(dbus::ObjectPath(body_sensor_location_path_));
  NotifyCharacteristicRemoved(dbus::ObjectPath(heart_rate_control_point_path_));

  heart_rate_measurement_properties_.reset();
  body_sensor_location_properties_.reset();
  heart_rate_control_point_properties_.reset();

  heart_rate_measurement_path_.clear();
  body_sensor_location_path_.clear();
  heart_rate_control_point_path_.clear();
  heart_rate_visible_ = false;
}

void FakeBluetoothGattCharacteristicClient::SetExtraProcessing(
    size_t requests) {
  extra_requests_ = requests;
  if (extra_requests_ == 0) {
    for (const auto& it : action_extra_requests_) {
      it.second->callback_.Run();
      delete it.second;
    }
    action_extra_requests_.clear();
    return;
  }
  VLOG(2) << "Requests SLOW now, " << requests << " InProgress errors each.";
}

size_t FakeBluetoothGattCharacteristicClient::GetExtraProcessing() const {
  return extra_requests_;
}

dbus::ObjectPath
FakeBluetoothGattCharacteristicClient::GetHeartRateMeasurementPath() const {
  return dbus::ObjectPath(heart_rate_measurement_path_);
}

dbus::ObjectPath
FakeBluetoothGattCharacteristicClient::GetBodySensorLocationPath() const {
  return dbus::ObjectPath(body_sensor_location_path_);
}

dbus::ObjectPath
FakeBluetoothGattCharacteristicClient::GetHeartRateControlPointPath() const {
  return dbus::ObjectPath(heart_rate_control_point_path_);
}

void FakeBluetoothGattCharacteristicClient::OnPropertyChanged(
    const dbus::ObjectPath& object_path,
    const std::string& property_name) {
  VLOG(2) << "Characteristic property changed: " << object_path.value() << ": "
          << property_name;

  for (auto& observer : observers_)
    observer.GattCharacteristicPropertyChanged(object_path, property_name);
}

void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicAdded(
    const dbus::ObjectPath& object_path) {
  VLOG(2) << "GATT characteristic added: " << object_path.value();
  for (auto& observer : observers_)
    observer.GattCharacteristicAdded(object_path);
}

void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicRemoved(
    const dbus::ObjectPath& object_path) {
  VLOG(2) << "GATT characteristic removed: " << object_path.value();
  for (auto& observer : observers_)
    observer.GattCharacteristicRemoved(object_path);
}

void FakeBluetoothGattCharacteristicClient::
    ScheduleHeartRateMeasurementValueChange() {
  if (!IsHeartRateVisible())
    return;

  // Don't send updates if the characteristic is not notifying.
  if (!heart_rate_measurement_properties_->notifying.value())
    return;

  VLOG(2) << "Updating heart rate value.";
  std::vector<uint8_t> measurement = GetHeartRateMeasurementValue();
  heart_rate_measurement_properties_->value.ReplaceValue(measurement);

  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&FakeBluetoothGattCharacteristicClient::
                         ScheduleHeartRateMeasurementValueChange,
                     weak_ptr_factory_.GetWeakPtr()),
      base::TimeDelta::FromMilliseconds(
          kHeartRateMeasurementNotificationIntervalMs));
}

void FakeBluetoothGattCharacteristicClient::DelayedReadValueCallback(
    const dbus::ObjectPath& object_path,
    const ValueCallback& callback,
    const std::vector<uint8_t>& value) {
  Properties* properties = GetProperties(object_path);
  DCHECK(properties);

  properties->value.ReplaceValue(value);
  callback.Run(value);
}

std::vector<uint8_t>
FakeBluetoothGattCharacteristicClient::GetHeartRateMeasurementValue() {
  // TODO(armansito): We should make sure to properly pack this struct to ensure
  // correct byte alignment and endianness. It doesn't matter too much right now
  // as this is a fake and GCC on Linux seems to do the right thing.
  struct {
    uint8_t flags;
    uint8_t bpm;
    uint16_t energy_expanded;
    uint16_t rr_interval;
  } value;

  // Flags in LSB:     0       11   1 1 000
  //                   |       |    | | |
  // 8-bit bpm format --       |    | | |
  // Sensor contact supported --    | | |
  // Energy expanded field present -- | |
  // RR-Interval values present ------- |
  // Reserved for future use ------------
  value.flags = 0x0;
  value.flags |= (0x03 << 1);
  value.flags |= (0x01 << 3);
  value.flags |= (0x01 << 4);

  // Pick a value between 117 bpm and 153 bpm for heart rate.
  value.bpm = static_cast<uint8_t>(base::RandInt(117, 153));

  // Total calories burned in kJoules since the last reset. Increment this by 1
  // every time. It's fine if it overflows: it becomes 0 when the user resets
  // the heart rate monitor (or pretend that they had a lot of cheeseburgers).
  value.energy_expanded = calories_burned_++;

  // Include one RR-Interval value, in seconds.
  value.rr_interval = 60 / value.bpm;

  // Return the bytes in an array.
  uint8_t* bytes = reinterpret_cast<uint8_t*>(&value);
  std::vector<uint8_t> return_value;
  return_value.assign(bytes, bytes + sizeof(value));
  return return_value;
}

bool FakeBluetoothGattCharacteristicClient::IsHeartRateVisible() const {
  DCHECK(heart_rate_visible_ != heart_rate_measurement_path_.empty());
  DCHECK(heart_rate_visible_ != body_sensor_location_path_.empty());
  DCHECK(heart_rate_visible_ != heart_rate_control_point_path_.empty());
  DCHECK(heart_rate_visible_ == !!heart_rate_measurement_properties_.get());
  DCHECK(heart_rate_visible_ == !!body_sensor_location_properties_.get());
  DCHECK(heart_rate_visible_ == !!heart_rate_control_point_properties_.get());
  return heart_rate_visible_;
}

}  // namespace bluez
