//
//  Copyright 2015 Google, Inc.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at:
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

#include "service/gatt_server.h"

#include <base/logging.h>

#include "service/logging_helpers.h"
#include "stack/include/bt_types.h"
#include "types/raw_address.h"

using std::lock_guard;
using std::mutex;

namespace bluetooth {

// GattServer implementation

GattServer::GattServer(const Uuid& uuid, int server_id)
    : app_identifier_(uuid), server_id_(server_id), delegate_(nullptr) {}

GattServer::~GattServer() {
  // Automatically unregister the server.
  VLOG(1) << "GattServer unregistering: " << server_id_;

  // Unregister as observer so we no longer receive any callbacks.
  hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);

  // Unregister this server, stop all services, and ignore the result.
  // TODO(armansito): stop and remove all services here? unregister_server
  // should really take care of that.
  hal::BluetoothGattInterface::Get()
      ->GetServerHALInterface()
      ->unregister_server(server_id_);
}

void GattServer::SetDelegate(Delegate* delegate) {
  lock_guard<mutex> lock(mutex_);
  delegate_ = delegate;
}

const Uuid& GattServer::GetAppIdentifier() const { return app_identifier_; }

int GattServer::GetInstanceId() const { return server_id_; }

bool GattServer::AddService(const bluetooth::Service& service,
                            const ResultCallback& callback) {
  VLOG(1) << __func__ << " server_id: " << server_id_;
  lock_guard<mutex> lock(mutex_);

  if (!callback) {
    LOG(ERROR) << "|callback| cannot be NULL";
    return false;
  }

  std::vector<btgatt_db_element_t> svc;

  svc.push_back({
      .uuid = service.uuid(),
      .type = (service.primary() ? BTGATT_DB_PRIMARY_SERVICE
                                 : BTGATT_DB_SECONDARY_SERVICE),
  });

  for (const auto& characteristic : service.characteristics()) {
    svc.push_back({.uuid = characteristic.uuid(),
                   .type = BTGATT_DB_CHARACTERISTIC,
                   .properties = characteristic.properties(),
                   .permissions = characteristic.permissions()});
    for (const auto& descriptor : characteristic.descriptors())
      svc.push_back({.uuid = descriptor.uuid(),
                     .type = BTGATT_DB_DESCRIPTOR,
                     .permissions = descriptor.permissions()});
  }

  for (const auto& incl_svc : service.included_services())
    svc.push_back({.type = BTGATT_DB_INCLUDED_SERVICE,
                   .attribute_handle = incl_svc.handle()});

  pending_end_decl_cb_ = callback;

  bt_status_t status =
      hal::BluetoothGattInterface::Get()->GetServerHALInterface()->add_service(
          server_id_, svc.data(), svc.size());
  if (status != BT_STATUS_SUCCESS) {
    LOG(ERROR) << "Failed to initiate call to populate GATT service";
    CleanUpPendingData();
    return false;
  }

  return true;
}

bool GattServer::SendResponse(const std::string& device_address, int request_id,
                              GATTError error, int offset,
                              const std::vector<uint8_t>& value) {
  VLOG(1) << __func__ << " - server_id: " << server_id_
          << " device_address: " << device_address
          << " request_id: " << request_id << " error: " << error
          << " offset: " << offset;
  lock_guard<mutex> lock(mutex_);

  RawAddress addr;
  if (!RawAddress::FromString(device_address, addr)) {
    LOG(ERROR) << "Invalid device address given: " << device_address;
    return false;
  }

  if (offset < 0) {
    LOG(ERROR) << "Offset is less than 0 offset: " << offset;
    return false;
  }

  if (value.size() + offset > BTGATT_MAX_ATTR_LEN) {
    LOG(ERROR) << "Value is too large";
    return false;
  }

  // Find the correct connection ID for |device_address| and |request_id|.
  auto iter = conn_addr_map_.find(device_address);
  if (iter == conn_addr_map_.end()) {
    LOG(ERROR) << "No known connections for device address: " << device_address;
    return false;
  }

  std::shared_ptr<Connection> connection;
  for (const auto& tmp : iter->second) {
    if (tmp->request_id_to_handle.find(request_id) ==
        tmp->request_id_to_handle.end())
      continue;

    connection = tmp;
  }

  if (!connection) {
    LOG(ERROR) << "Pending request with ID " << request_id
               << " not found for device with BD_ADDR: " << device_address;
    return false;
  }

  btgatt_response_t response;
  memset(&response, 0, sizeof(response));

  // We keep -1 as the handle for "Execute Write Request". In that case,
  // there is no need to populate the response data. Just send zeros back.
  int handle = connection->request_id_to_handle[request_id];
  response.handle = handle;
  response.attr_value.handle = handle;
  if (handle != -1) {
    memcpy(response.attr_value.value, value.data(), value.size());
    response.attr_value.offset = offset;
    response.attr_value.len = value.size();
  }

  bt_status_t result =
      hal::BluetoothGattInterface::Get()
          ->GetServerHALInterface()
          ->send_response(connection->conn_id, request_id, error, response);
  if (result != BT_STATUS_SUCCESS) {
    LOG(ERROR) << "Failed to initiate call to send GATT response";
    return false;
  }

  connection->request_id_to_handle.erase(request_id);

  return true;
}

bool GattServer::SendNotification(const std::string& device_address,
                                  const uint16_t handle, bool confirm,
                                  const std::vector<uint8_t>& value,
                                  const GattCallback& callback) {
  VLOG(1) << " - server_id: " << server_id_
          << " device_address: " << device_address << " confirm: " << confirm;
  lock_guard<mutex> lock(mutex_);

  RawAddress addr;
  if (!RawAddress::FromString(device_address, addr)) {
    LOG(ERROR) << "Invalid device address given: " << device_address;
    return false;
  }

  // Get the connection IDs for which we will send this notification.
  auto conn_iter = conn_addr_map_.find(device_address);
  if (conn_iter == conn_addr_map_.end()) {
    LOG(ERROR) << "No known connections for device with address: "
               << device_address;
    return false;
  }

  std::shared_ptr<PendingIndication> pending_ind(
      new PendingIndication(callback));

  // Send the notification/indication on all matching connections.
  int send_count = 0;
  for (const auto& conn : conn_iter->second) {
    // Make sure that one isn't already pending for this connection.
    if (pending_indications_.find(conn->conn_id) !=
        pending_indications_.end()) {
      VLOG(1) << "A" << (confirm ? "n indication" : " notification")
              << " is already pending for connection: " << conn->conn_id;
      continue;
    }

    // The HAL API takes char* rather const char* for |value|, so we have to
    // cast away the const.
    // TODO(armansito): Make HAL accept const char*.
    bt_status_t status =
        hal::BluetoothGattInterface::Get()
            ->GetServerHALInterface()
            ->send_indication(server_id_, handle, conn->conn_id, confirm,
                              value.data(), value.size());

    // Increment the send count if this was successful. We don't immediately
    // fail if the HAL returned an error. It's better to report success as long
    // as we sent out at least one notification to this device as
    // multi-transport GATT connections from the same BD_ADDR will be rare
    // enough already.
    if (status != BT_STATUS_SUCCESS) continue;

    send_count++;
    pending_indications_[conn->conn_id] = pending_ind;
  }

  if (send_count == 0) {
    LOG(ERROR) << "Failed to send notifications/indications to device: "
               << device_address;
    return false;
  }

  return true;
}

void GattServer::ConnectionCallback(
    hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int server_id,
    int connected, const RawAddress& bda) {
  lock_guard<mutex> lock(mutex_);

  if (server_id != server_id_) return;

  std::string device_address = BtAddrString(&bda);

  VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
          << " BD_ADDR: " << device_address;

  if (!connected) {
    // Erase the entry if we were connected to it.
    VLOG(1) << "No longer connected: " << device_address;
    conn_id_map_.erase(conn_id);
    auto iter = conn_addr_map_.find(device_address);
    if (iter == conn_addr_map_.end()) return;

    // Remove the appropriate connection objects in the address.
    for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
         ++conn_iter) {
      if ((*conn_iter)->conn_id != conn_id) continue;

      iter->second.erase(conn_iter);
      break;
    }

    if (delegate_)
      delegate_->OnConnectionStateChanged(this, device_address, false);

    return;
  }

  if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
    LOG(WARNING) << "Connection entry already exists; "
                 << "ignoring ConnectionCallback";
    return;
  }

  LOG(INFO) << "Added connection entry for conn_id: " << conn_id
            << " device address: " << device_address;
  std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
  conn_id_map_[conn_id] = connection;
  conn_addr_map_[device_address].push_back(connection);

  if (delegate_)
    delegate_->OnConnectionStateChanged(this, device_address, true);
}

void GattServer::ServiceAddedCallback(hal::BluetoothGattInterface* gatt_iface,
                                      int status, int server_id,
                                      std::vector<btgatt_db_element_t> svc) {
  lock_guard<mutex> lock(mutex_);

  if (server_id != server_id_) return;

  VLOG(1) << __func__ << " - status: " << status << " server_id: " << server_id
          << " first handle: " << svc[0].attribute_handle
          << " service Uuid: " << Uuid(svc[0].uuid).ToString()
          << " count: " << svc.size();

  Service service(svc[0].attribute_handle, true, Uuid(svc[0].uuid), {}, {});

  for (size_t i = 1; i < svc.size(); i++) {
    const btgatt_db_element_t& curr = svc[i];
    VLOG(1) << " - processing item no: " << i
            << " handle: " << curr.attribute_handle;
    if (curr.type == BTGATT_DB_CHARACTERISTIC) {
      service.characteristics().push_back({curr.attribute_handle,
                                           Uuid(curr.uuid),
                                           curr.properties,
                                           curr.permissions,
                                           {}});
    } else if (curr.type == BTGATT_DB_DESCRIPTOR) {
      service.characteristics().back().descriptors().push_back(
          {curr.attribute_handle, Uuid(curr.uuid), curr.permissions});
    } else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) {
    }
  }

  pending_end_decl_cb_((bluetooth::BLEStatus)status, service);

  CleanUpPendingData();
}

void GattServer::ServiceStoppedCallback(
    hal::BluetoothGattInterface* /* gatt_iface */, int /* status */,
    int /* server_id */, int /* service_handle */) {
  // TODO(armansito): Support stopping a service.
}

void GattServer::RequestReadCharacteristicCallback(
    hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
    const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
  lock_guard<mutex> lock(mutex_);

  // Check to see if we know about this connection. Otherwise ignore the
  // request.
  auto conn = GetConnection(conn_id, bda, trans_id);
  if (!conn) return;

  std::string device_address = BtAddrString(&bda);

  VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
          << " BD_ADDR: " << device_address
          << " attribute_handle: " << attribute_handle << " offset: " << offset
          << " is_long: " << is_long;

  conn->request_id_to_handle[trans_id] = attribute_handle;

  // If there is no delegate then there is nobody to handle request. The request
  // will eventually timeout and we should get a connection update that
  // terminates the connection.
  if (!delegate_) {
    // TODO(armansito): Require a delegate at server registration so that this
    // is never possible.
    LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
                 << "will time out.";
    return;
  }

  delegate_->OnCharacteristicReadRequest(this, device_address, trans_id, offset,
                                         is_long, attribute_handle);
}
void GattServer::RequestReadDescriptorCallback(
    hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
    const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
  lock_guard<mutex> lock(mutex_);

  // Check to see if we know about this connection. Otherwise ignore the
  // request.
  auto conn = GetConnection(conn_id, bda, trans_id);
  if (!conn) return;

  std::string device_address = BtAddrString(&bda);

  VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
          << " BD_ADDR: " << device_address
          << " attribute_handle: " << attribute_handle << " offset: " << offset
          << " is_long: " << is_long;

  conn->request_id_to_handle[trans_id] = attribute_handle;

  // If there is no delegate then there is nobody to handle request. The request
  // will eventually timeout and we should get a connection update that
  // terminates the connection.
  if (!delegate_) {
    // TODO(armansito): Require a delegate at server registration so that this
    // is never possible.
    LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
                 << "will time out.";
    return;
  }

  delegate_->OnDescriptorReadRequest(this, device_address, trans_id, offset,
                                     is_long, attribute_handle);
}

void GattServer::RequestWriteCharacteristicCallback(
    hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
    const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
    bool is_prep, std::vector<uint8_t> value) {
  lock_guard<mutex> lock(mutex_);

  // Check to see if we know about this connection. Otherwise ignore the
  // request.
  auto conn = GetConnection(conn_id, bda, trans_id);
  if (!conn) return;

  std::string device_address = BtAddrString(&bda);

  VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
          << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
          << " offset: " << offset << " length: " << value.size()
          << " need_rsp: " << need_rsp << " is_prep: " << is_prep;

  // Store the request ID only if this is not a write-without-response. If
  // another request occurs after this with the same request ID, then we'll
  // simply process it normally, though that shouldn't ever happen.
  if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;

  // If there is no delegate then there is nobody to handle request. The request
  // will eventually timeout and we should get a connection update that
  // terminates the connection.
  if (!delegate_) {
    // TODO(armansito): Require a delegate at server registration so that this
    // is never possible.
    LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
                 << "will time out.";
    return;
  }

  delegate_->OnCharacteristicWriteRequest(this, device_address, trans_id,
                                          offset, is_prep, need_rsp,
                                          std::move(value), attr_handle);
}

void GattServer::RequestWriteDescriptorCallback(
    hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
    const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
    bool is_prep, std::vector<uint8_t> value) {
  lock_guard<mutex> lock(mutex_);

  // Check to see if we know about this connection. Otherwise ignore the
  // request.
  auto conn = GetConnection(conn_id, bda, trans_id);
  if (!conn) return;

  std::string device_address = BtAddrString(&bda);

  VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
          << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
          << " offset: " << offset << " length: " << value.size()
          << " need_rsp: " << need_rsp << " is_prep: " << is_prep;

  // Store the request ID only if this is not a write-without-response. If
  // another request occurs after this with the same request ID, then we'll
  // simply process it normally, though that shouldn't ever happen.
  if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;

  // If there is no delegate then there is nobody to handle request. The request
  // will eventually timeout and we should get a connection update that
  // terminates the connection.
  if (!delegate_) {
    // TODO(armansito): Require a delegate at server registration so that this
    // is never possible.
    LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
                 << "will time out.";
    return;
  }

  delegate_->OnDescriptorWriteRequest(this, device_address, trans_id, offset,
                                      is_prep, need_rsp, std::move(value),
                                      attr_handle);
}

void GattServer::RequestExecWriteCallback(
    hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
    const RawAddress& bda, int exec_write) {
  lock_guard<mutex> lock(mutex_);

  // Check to see if we know about this connection. Otherwise ignore the
  // request.
  auto conn = GetConnection(conn_id, bda, trans_id);
  if (!conn) return;

  std::string device_address = BtAddrString(&bda);

  VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
          << " BD_ADDR: " << device_address << " exec_write: " << exec_write;

  // Just store a dummy invalid handle as this request doesn't apply to a
  // specific handle.
  conn->request_id_to_handle[trans_id] = -1;

  // If there is no delegate then there is nobody to handle request. The request
  // will eventually timeout and we should get a connection update that
  // terminates the connection.
  if (!delegate_) {
    // TODO(armansito): Require a delegate at server registration so that this
    // is never possible.
    LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
                 << "will time out.";
    return;
  }

  delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
}

void GattServer::IndicationSentCallback(
    hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int status) {
  VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status;
  lock_guard<mutex> lock(mutex_);

  const auto& pending_ind_iter = pending_indications_.find(conn_id);
  if (pending_ind_iter == pending_indications_.end()) {
    VLOG(1) << "Unknown connection: " << conn_id;
    return;
  }

  std::shared_ptr<PendingIndication> pending_ind = pending_ind_iter->second;
  pending_indications_.erase(pending_ind_iter);

  if (status == BT_STATUS_SUCCESS) pending_ind->has_success = true;

  // Invoke it if this was the last reference to the confirmation callback.
  if (pending_ind.unique() && pending_ind->callback) {
    pending_ind->callback(pending_ind->has_success
                              ? GATT_ERROR_NONE
                              : static_cast<GATTError>(status));
  }
}

void GattServer::CleanUpPendingData() {
  pending_end_decl_cb_ = ResultCallback();
}

std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
    int conn_id, const RawAddress& bda, int request_id) {
  auto iter = conn_id_map_.find(conn_id);
  if (iter == conn_id_map_.end()) {
    VLOG(1) << "Connection doesn't belong to this server";
    return nullptr;
  }

  auto conn = iter->second;
  if (conn->bdaddr != bda) {
    LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
                 << "connection ID: " << conn_id;
    return nullptr;
  }

  if (conn->request_id_to_handle.find(request_id) !=
      conn->request_id_to_handle.end()) {
    VLOG(1) << "Request with ID: " << request_id << " already exists for "
            << " connection: " << conn_id;
    return nullptr;
  }

  return conn;
}

// GattServerFactory implementation

GattServerFactory::GattServerFactory() {
  hal::BluetoothGattInterface::Get()->AddServerObserver(this);
}

GattServerFactory::~GattServerFactory() {
  hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
}

bool GattServerFactory::RegisterInstance(const Uuid& uuid,
                                         const RegisterCallback& callback) {
  VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
  lock_guard<mutex> lock(pending_calls_lock_);

  if (pending_calls_.find(uuid) != pending_calls_.end()) {
    LOG(ERROR) << "GATT-server client with given Uuid already being registered "
               << " - Uuid: " << uuid.ToString();
    return false;
  }

  const btgatt_server_interface_t* hal_iface =
      hal::BluetoothGattInterface::Get()->GetServerHALInterface();

  if (hal_iface->register_server(uuid, false) != BT_STATUS_SUCCESS)
    return false;

  pending_calls_[uuid] = callback;

  return true;
}

void GattServerFactory::RegisterServerCallback(
    hal::BluetoothGattInterface* gatt_iface, int status, int server_id,
    const Uuid& app_uuid) {
  Uuid uuid(app_uuid);

  VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
  lock_guard<mutex> lock(pending_calls_lock_);

  auto iter = pending_calls_.find(uuid);
  if (iter == pending_calls_.end()) {
    VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
    return;
  }

  // No need to construct a server if the call wasn't successful.
  std::unique_ptr<GattServer> server;
  BLEStatus result = BLE_STATUS_FAILURE;
  if (status == BT_STATUS_SUCCESS) {
    server.reset(new GattServer(uuid, server_id));

    gatt_iface->AddServerObserver(server.get());

    result = BLE_STATUS_SUCCESS;
  }

  // Notify the result via the result callback.
  iter->second(result, uuid, std::move(server));

  pending_calls_.erase(iter);
}

}  // namespace bluetooth
