/*
 * Copyright 2018 The Android Open Source Project
 *
 * 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 "connection_handler.h"

#include <base/bind.h>
#include <base/logging.h>
#include <map>

#include "avrc_defs.h"
#include "avrcp_message_converter.h"
#include "bt_types.h"
#include "btu.h"
#include "packet/avrcp/avrcp_packet.h"
// TODO (apanicke): Remove dependency on this header once we cleanup feature
// handling.
#include "bta/include/bta_av_api.h"
#include "device/include/interop.h"
#include "osi/include/allocator.h"
#include "osi/include/properties.h"

namespace bluetooth {
namespace avrcp {

ConnectionHandler* ConnectionHandler::instance_ = nullptr;

ConnectionHandler* ConnectionHandler::Get() {
  CHECK(instance_);

  return instance_;
}

bool IsAbsoluteVolumeEnabled(const RawAddress* bdaddr) {
  char volume_disabled[PROPERTY_VALUE_MAX] = {0};
  osi_property_get("persist.bluetooth.disableabsvol", volume_disabled, "false");
  if (strncmp(volume_disabled, "true", 4) == 0) {
    LOG(INFO) << "Absolute volume disabled by property";
    return false;
  }
  if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, bdaddr)) {
    LOG(INFO) << "Absolute volume disabled by IOP table";
    return false;
  }
  return true;
}

bool ConnectionHandler::Initialize(const ConnectionCallback& callback,
                                   AvrcpInterface* avrcp, SdpInterface* sdp,
                                   VolumeInterface* vol) {
  CHECK(instance_ == nullptr);
  CHECK(avrcp != nullptr);
  CHECK(sdp != nullptr);

  // TODO (apanicke): When transitioning to using this service, implement
  // SDP Initialization for AVRCP Here.
  instance_ = new ConnectionHandler();
  instance_->connection_cb_ = callback;
  instance_->avrc_ = avrcp;
  instance_->sdp_ = sdp;
  instance_->vol_ = vol;

  // Set up the AVRCP acceptor connection
  if (!instance_->AvrcpConnect(false, RawAddress::kAny)) {
    instance_->CleanUp();
    return false;
  }

  return true;
}

bool ConnectionHandler::CleanUp() {
  CHECK(instance_ != nullptr);

  // TODO (apanicke): Cleanup the SDP Entries here
  for (auto entry = instance_->device_map_.begin();
       entry != instance_->device_map_.end();) {
    auto curr = entry;
    entry++;
    curr->second->DeviceDisconnected();
    instance_->avrc_->Close(curr->first);
  }
  instance_->device_map_.clear();
  instance_->feature_map_.clear();

  instance_->weak_ptr_factory_.InvalidateWeakPtrs();

  delete instance_;
  instance_ = nullptr;

  return true;
}

void ConnectionHandler::InitForTesting(ConnectionHandler* handler) {
  CHECK(instance_ == nullptr);
  instance_ = handler;
}

bool ConnectionHandler::ConnectDevice(const RawAddress& bdaddr) {
  LOG(INFO) << "Attempting to connect to device " << bdaddr;

  for (const auto& pair : device_map_) {
    if (bdaddr == pair.second->GetAddress()) {
      LOG(WARNING) << "Already connected to device with address " << bdaddr;
      return false;
    }
  }

  auto connection_lambda = [](ConnectionHandler* instance_,
                              const RawAddress& bdaddr, uint16_t status,
                              uint16_t version, uint16_t features) {
    LOG(INFO) << __PRETTY_FUNCTION__
              << " SDP Completed features=" << loghex(features);
    if (status != AVRC_SUCCESS || !(features & BTA_AV_FEAT_RCCT)) {
      LOG(ERROR) << "Failed to do SDP: status=" << loghex(status)
                 << " features=" << loghex(features)
                 << " supports controller: " << (features & BTA_AV_FEAT_RCCT);
      instance_->connection_cb_.Run(std::shared_ptr<Device>());
    }

    instance_->feature_map_.emplace(bdaddr, features);
    instance_->AvrcpConnect(true, bdaddr);
    return;
  };

  return SdpLookup(bdaddr, base::Bind(connection_lambda, this, bdaddr), false);
}

bool ConnectionHandler::DisconnectDevice(const RawAddress& bdaddr) {
  for (auto it = device_map_.begin(); it != device_map_.end(); it++) {
    if (bdaddr == it->second->GetAddress()) {
      uint8_t handle = it->first;
      return avrc_->Close(handle) == AVRC_SUCCESS;
    }
  }

  return false;
}

void ConnectionHandler::SetBipClientStatus(const RawAddress& bdaddr,
                                           bool connected) {
  for (auto it = device_map_.begin(); it != device_map_.end(); it++) {
    if (bdaddr == it->second->GetAddress()) {
      it->second->SetBipClientStatus(connected);
      return;
    }
  }
}

std::vector<std::shared_ptr<Device>> ConnectionHandler::GetListOfDevices()
    const {
  std::vector<std::shared_ptr<Device>> list;
  for (const auto& device : device_map_) {
    list.push_back(device.second);
  }
  return list;
}

bool ConnectionHandler::SdpLookup(const RawAddress& bdaddr, SdpCallback cb,
                                  bool retry) {
  LOG(INFO) << __PRETTY_FUNCTION__;

  tAVRC_SDP_DB_PARAMS db_params;
  // TODO (apanicke): This needs to be replaced with smarter memory management.
  tSDP_DISCOVERY_DB* disc_db =
      (tSDP_DISCOVERY_DB*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
  uint16_t attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
                          ATTR_ID_BT_PROFILE_DESC_LIST,
                          ATTR_ID_SUPPORTED_FEATURES};

  db_params.db_len =
      BT_DEFAULT_BUFFER_SIZE;  // Some magic number found in the AVRCP code
  db_params.num_attr = sizeof(attr_list) / sizeof(attr_list[0]);
  db_params.p_db = disc_db;
  db_params.p_attrs = attr_list;

  return avrc_->FindService(UUID_SERVCLASS_AV_REMOTE_CONTROL, bdaddr,
                            &db_params,
                            base::Bind(&ConnectionHandler::SdpCb,
                                       weak_ptr_factory_.GetWeakPtr(), bdaddr,
                                       cb, disc_db, retry)) == AVRC_SUCCESS;
}

bool ConnectionHandler::AvrcpConnect(bool initiator, const RawAddress& bdaddr) {
  LOG(INFO) << "Connect to device " << bdaddr.ToString();

  tAVRC_CONN_CB open_cb;
  if (initiator) {
    open_cb.ctrl_cback = base::Bind(&ConnectionHandler::InitiatorControlCb,
                                    weak_ptr_factory_.GetWeakPtr());
  } else {
    open_cb.ctrl_cback = base::Bind(&ConnectionHandler::AcceptorControlCb,
                                    weak_ptr_factory_.GetWeakPtr());
  }
  open_cb.msg_cback =
      base::Bind(&ConnectionHandler::MessageCb, weak_ptr_factory_.GetWeakPtr());
  open_cb.company_id = AVRC_CO_GOOGLE;
  open_cb.conn = initiator ? AVRC_CONN_INT
                           : AVRC_CONN_ACP;  // 0 if initiator, 1 if acceptor
  // TODO (apanicke): We shouldn't need RCCT to do absolute volume. The current
  // AVRC_API requires it though.
  open_cb.control = BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_METADATA
                    | AVRC_CT_PASSIVE;

  uint8_t handle = 0;
  uint16_t status = avrc_->Open(&handle, &open_cb, bdaddr);
  LOG(INFO) << __PRETTY_FUNCTION__ << ": handle=" << loghex(handle)
            << " status= " << loghex(status);
  return status == AVRC_SUCCESS;
}

void ConnectionHandler::InitiatorControlCb(uint8_t handle, uint8_t event,
                                           uint16_t result,
                                           const RawAddress* peer_addr) {
  DCHECK(!connection_cb_.is_null());

  LOG(INFO) << __PRETTY_FUNCTION__ << ": handle=" << loghex(handle)
            << " result=" << loghex(result)
            << " addr=" << (peer_addr ? peer_addr->ToString() : "none");

  switch (event) {
    case AVRC_OPEN_IND_EVT: {
      LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Opened Event";

      const auto& feature_iter = feature_map_.find(*peer_addr);
      if (feature_iter == feature_map_.end()) {
        LOG(ERROR) << "Features do not exist even though SDP should have been "
                      "done first";
        return;
      }

      bool supports_browsing = feature_iter->second & BTA_AV_FEAT_BROWSE;

      if (supports_browsing) {
        avrc_->OpenBrowse(handle, AVCT_INT);
      }

      // TODO (apanicke): Implement a system to cache SDP entries. For most
      // devices SDP is completed after the device connects AVRCP so that
      // information isn't very useful when trying to control our
      // capabilities. For now always use AVRCP 1.6.
      auto&& callback = base::Bind(&ConnectionHandler::SendMessage,
                                   base::Unretained(this), handle);
      auto&& ctrl_mtu = avrc_->GetPeerMtu(handle) - AVCT_HDR_LEN;
      auto&& browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
      std::shared_ptr<Device> newDevice = std::make_shared<Device>(
          *peer_addr, !supports_browsing, callback, ctrl_mtu, browse_mtu);

      device_map_[handle] = newDevice;
      // TODO (apanicke): Create the device with all of the interfaces it
      // needs. Return the new device where the service will register the
      // interfaces it needs.
      connection_cb_.Run(newDevice);

      if (feature_iter->second & BTA_AV_FEAT_ADV_CTRL) {
        newDevice->RegisterVolumeChanged();
      } else if (instance_->vol_ != nullptr) {
        instance_->vol_->DeviceConnected(newDevice->GetAddress());
      }

    } break;

    case AVRC_CLOSE_IND_EVT: {
      LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Closed Event";

      if (device_map_.find(handle) == device_map_.end()) {
        LOG(WARNING)
            << "Connection Close received from device that doesn't exist";
        return;
      }
      avrc_->Close(handle);
      feature_map_.erase(device_map_[handle]->GetAddress());
      device_map_[handle]->DeviceDisconnected();
      device_map_.erase(handle);
    } break;

    case AVRC_BROWSE_OPEN_IND_EVT: {
      LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Open Event";
      // NOTE (apanicke): We don't need to explicitly handle this message
      // since the AVCTP Layer will still send us browsing messages
      // regardless. It would be useful to note this though for future
      // compatibility issues.
      if (device_map_.find(handle) == device_map_.end()) {
        LOG(WARNING) << "Browse Opened received from device that doesn't exist";
        return;
      }

      auto browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
      device_map_[handle]->SetBrowseMtu(browse_mtu);
    } break;
    case AVRC_BROWSE_CLOSE_IND_EVT:
      LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Close Event";
      break;
    default:
      LOG(ERROR) << "Unknown AVRCP Control event";
      break;
  }
}

void ConnectionHandler::AcceptorControlCb(uint8_t handle, uint8_t event,
                                          uint16_t result,
                                          const RawAddress* peer_addr) {
  DCHECK(!connection_cb_.is_null());

  LOG(INFO) << __PRETTY_FUNCTION__ << ": handle=" << loghex(handle)
            << " result=" << loghex(result)
            << " addr=" << (peer_addr ? peer_addr->ToString() : "none");

  switch (event) {
    case AVRC_OPEN_IND_EVT: {
      LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Opened Event";

      auto&& callback = base::Bind(&ConnectionHandler::SendMessage,
                                   weak_ptr_factory_.GetWeakPtr(), handle);
      auto&& ctrl_mtu = avrc_->GetPeerMtu(handle) - AVCT_HDR_LEN;
      auto&& browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
      std::shared_ptr<Device> newDevice = std::make_shared<Device>(
          *peer_addr, false, callback, ctrl_mtu, browse_mtu);

      device_map_[handle] = newDevice;
      connection_cb_.Run(newDevice);

      LOG(INFO) << __PRETTY_FUNCTION__
                << ": Performing SDP on connected device. address="
                << peer_addr->ToString();
      auto sdp_lambda = [](ConnectionHandler* instance_, uint8_t handle,
                           uint16_t status, uint16_t version,
                           uint16_t features) {
        if (instance_->device_map_.find(handle) ==
            instance_->device_map_.end()) {
          LOG(WARNING) << __PRETTY_FUNCTION__
                       << ": No device found for handle: " << loghex(handle);
          return;
        }

        auto device = instance_->device_map_[handle];
        instance_->feature_map_.emplace(device->GetAddress(), features);

        // TODO (apanicke): Report to the VolumeInterface that a new Device is
        // connected that doesn't support absolute volume.
        if (features & BTA_AV_FEAT_ADV_CTRL) {
          device->RegisterVolumeChanged();
        } else if (instance_->vol_ != nullptr) {
          instance_->vol_->DeviceConnected(device->GetAddress());
        }
      };

      SdpLookup(*peer_addr, base::Bind(sdp_lambda, this, handle), false);

      avrc_->OpenBrowse(handle, AVCT_ACP);
      AvrcpConnect(false, RawAddress::kAny);
    } break;

    case AVRC_CLOSE_IND_EVT: {
      LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Closed Event";

      if (device_map_.find(handle) == device_map_.end()) {
        LOG(WARNING)
            << "Connection Close received from device that doesn't exist";
        return;
      }
      avrc_->Close(handle);
      feature_map_.erase(device_map_[handle]->GetAddress());
      device_map_[handle]->DeviceDisconnected();
      device_map_.erase(handle);
    } break;

    case AVRC_BROWSE_OPEN_IND_EVT: {
      LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Open Event";
      // NOTE (apanicke): We don't need to explicitly handle this message
      // since the AVCTP Layer will still send us browsing messages
      // regardless. It would be useful to note this though for future
      // compatibility issues.
      if (device_map_.find(handle) == device_map_.end()) {
        LOG(WARNING) << "Browse Opened received from device that doesn't exist";
        return;
      }

      auto browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
      device_map_[handle]->SetBrowseMtu(browse_mtu);
    } break;
    case AVRC_BROWSE_CLOSE_IND_EVT:
      LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Close Event";
      break;
    default:
      LOG(ERROR) << "Unknown AVRCP Control event";
      break;
  }
}

void ConnectionHandler::MessageCb(uint8_t handle, uint8_t label, uint8_t opcode,
                                  tAVRC_MSG* p_msg) {
  if (device_map_.find(handle) == device_map_.end()) {
    LOG(ERROR) << "Message received for unconnected device: handle="
               << loghex(handle);
    return;
  }

  auto pkt = AvrcpMessageConverter::Parse(p_msg);

  if (opcode == AVRC_OP_BROWSE) {
    VLOG(4) << "Browse Message received on handle " << (unsigned int)handle;
    device_map_[handle]->BrowseMessageReceived(label, BrowsePacket::Parse(pkt));
    return;
  }

  VLOG(4) << "Message received on handle " << (unsigned int)handle;
  device_map_[handle]->MessageReceived(label, Packet::Parse(pkt));
}

void ConnectionHandler::SdpCb(RawAddress bdaddr, SdpCallback cb,
                              tSDP_DISCOVERY_DB* disc_db, bool retry,
                              uint16_t status) {
  VLOG(1) << __PRETTY_FUNCTION__ << ": SDP lookup callback received";

  if (status == SDP_CONN_FAILED and !retry) {
    LOG(WARNING) << __PRETTY_FUNCTION__ << ": SDP Failure retry again";
    SdpLookup(bdaddr, cb, true);
    return;
  } else if (status != AVRC_SUCCESS) {
    LOG(ERROR) << __PRETTY_FUNCTION__
               << ": SDP Failure: status = " << (unsigned int)status;
    cb.Run(status, 0, 0);
    osi_free(disc_db);
    return;
  }

  // Check the peer features
  tSDP_DISC_REC* sdp_record = nullptr;
  uint16_t peer_features = 0;
  uint16_t peer_avrcp_version = 0;

  // TODO (apanicke): Replace this in favor of our own supported features.
  sdp_record =
      sdp_->FindServiceInDb(disc_db, UUID_SERVCLASS_AV_REMOTE_CONTROL, nullptr);
  if (sdp_record != nullptr) {
    LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
              << " supports remote control";
    peer_features |= BTA_AV_FEAT_RCCT;

    if ((sdp_->FindAttributeInRec(sdp_record, ATTR_ID_BT_PROFILE_DESC_LIST)) !=
        NULL) {
      /* get profile version (if failure, version parameter is not updated) */
      sdp_->FindProfileVersionInRec(
          sdp_record, UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_avrcp_version);
      VLOG(1) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
              << " peer avrcp version=" << loghex(peer_avrcp_version);

      if (peer_avrcp_version >= AVRC_REV_1_3) {
        // These are the standard features, another way to check this is to
        // search for CAT1 on the remote device
        VLOG(1) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
                << " supports metadata";
        peer_features |= (BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_METADATA);
      }
      if (peer_avrcp_version >= AVRC_REV_1_4) {
        /* get supported categories */
        VLOG(1) << __PRETTY_FUNCTION__ << " Get Supported categories";
        tSDP_DISC_ATTR* sdp_attribute =
            sdp_->FindAttributeInRec(sdp_record, ATTR_ID_SUPPORTED_FEATURES);
        if (sdp_attribute != NULL) {
          VLOG(1) << __PRETTY_FUNCTION__
                  << "Get Supported categories SDP ATTRIBUTES != null";
          uint16_t categories = sdp_attribute->attr_value.v.u16;
          if (categories & AVRC_SUPF_CT_CAT2) {
            VLOG(1) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
                    << " supports advanced control";
            if (IsAbsoluteVolumeEnabled(&bdaddr)) {
              peer_features |= (BTA_AV_FEAT_ADV_CTRL);
            }
          }
          if (categories & AVRC_SUPF_CT_BROWSE) {
            VLOG(1) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
                    << " supports browsing";
            peer_features |= (BTA_AV_FEAT_BROWSE);
          }
        }
      }
    }
  }

  sdp_record = sdp_->FindServiceInDb(disc_db, UUID_SERVCLASS_AV_REM_CTRL_TARGET,
                                     nullptr);
  if (sdp_record != nullptr) {
    VLOG(1) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
            << " supports remote control target";

    uint16_t peer_avrcp_target_version = 0;
    sdp_->FindProfileVersionInRec(sdp_record, UUID_SERVCLASS_AV_REMOTE_CONTROL,
                                  &peer_avrcp_target_version);
    VLOG(1) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
            << " peer avrcp target version="
            << loghex(peer_avrcp_target_version);

    if ((sdp_->FindAttributeInRec(sdp_record, ATTR_ID_BT_PROFILE_DESC_LIST)) !=
        NULL) {
      if (peer_avrcp_target_version >= AVRC_REV_1_4) {
        /* get supported categories */
        VLOG(1) << __PRETTY_FUNCTION__ << " Get Supported categories";
        tSDP_DISC_ATTR* sdp_attribute =
            sdp_->FindAttributeInRec(sdp_record, ATTR_ID_SUPPORTED_FEATURES);
        if (sdp_attribute != NULL) {
          VLOG(1) << __PRETTY_FUNCTION__
                  << "Get Supported categories SDP ATTRIBUTES != null";
          uint16_t categories = sdp_attribute->attr_value.v.u16;
          if (categories & AVRC_SUPF_CT_CAT2) {
            VLOG(1) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
                    << " supports advanced control";
            if (IsAbsoluteVolumeEnabled(&bdaddr)) {
              peer_features |= (BTA_AV_FEAT_ADV_CTRL);
            }
          }
        }
      }
    }
  }

  osi_free(disc_db);

  cb.Run(status, peer_avrcp_version, peer_features);
}

void ConnectionHandler::SendMessage(
    uint8_t handle, uint8_t label, bool browse,
    std::unique_ptr<::bluetooth::PacketBuilder> message) {
  std::shared_ptr<::bluetooth::Packet> packet = VectorPacket::Make();
  message->Serialize(packet);

  uint8_t ctype = AVRC_RSP_ACCEPT;
  if (!browse) {
    ctype =
        (uint8_t)(::bluetooth::Packet::Specialize<Packet>(packet)->GetCType());
  }

  DLOG(INFO) << "SendMessage to handle=" << loghex(handle);

  BT_HDR* pkt = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);

  pkt->offset = AVCT_MSG_OFFSET;
  // TODO (apanicke): Update this constant. Currently this is a unique event
  // used to tell the AVRCP API layer that the data is properly formatted and
  // doesn't need to be processed. In the future, this is the only place sending
  // the packet so none of these layer specific fields will be used.
  pkt->event = 0xFFFF;
  /* Handle for AVRCP fragment */
  uint16_t op_code = (uint16_t)(::bluetooth::Packet::Specialize<Packet>(packet)->GetOpcode());
  if (!browse && (op_code == (uint16_t)(Opcode::VENDOR))) {
    pkt->event = op_code;
  }

  // TODO (apanicke): This layer specific stuff can go away once we move over
  // to the new service.
  pkt->layer_specific = AVCT_DATA_CTRL;
  if (browse) {
    pkt->layer_specific = AVCT_DATA_BROWSE;
  }

  pkt->len = packet->size();
  uint8_t* p_data = (uint8_t*)(pkt + 1) + pkt->offset;
  for (auto it = packet->begin(); it != packet->end(); it++) {
    *p_data++ = *it;
  }

  avrc_->MsgReq(handle, label, ctype, pkt);
}

}  // namespace avrcp
}  // namespace bluetooth
