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

#include <base/bind.h>
#include <base/logging.h>
#include <base/task/cancelable_task_tracker.h>
#include <base/threading/thread.h>
#include <mutex>
#include <sstream>

#include "abstract_message_loop.h"
#include "btif_av.h"
#include "btif_common.h"
#include "btif_dm.h"
#include "device.h"
#include "stack/include/btu.h"

namespace bluetooth {
namespace avrcp {
// Static variables and interface definitions
AvrcpService* AvrcpService::instance_ = nullptr;
AvrcpService::ServiceInterfaceImpl* AvrcpService::service_interface_ = nullptr;

void do_in_avrcp_jni(const base::Closure& task) {
  do_in_jni_thread(FROM_HERE, task);
}

class A2dpInterfaceImpl : public A2dpInterface {
  RawAddress active_peer() override { return btif_av_source_active_peer(); }

  bool is_peer_in_silence_mode(const RawAddress& peer_address) override {
    return btif_av_is_peer_silenced(peer_address);
  }
} a2dp_interface_;

class AvrcpInterfaceImpl : public AvrcpInterface {
 public:
  uint16_t GetAvrcpVersion() {
    return AVRC_GetProfileVersion();
  }

  uint16_t AddRecord(uint16_t service_uuid, const char* p_service_name,
                     const char* p_provider_name, uint16_t categories,
                     uint32_t sdp_handle, bool browse_supported,
                     uint16_t profile_version,
                     uint16_t cover_art_psm) override {
    return AVRC_AddRecord(service_uuid, p_service_name, p_provider_name,
                          categories, sdp_handle, browse_supported,
                          profile_version, cover_art_psm);
  }

  uint16_t RemoveRecord(uint32_t sdp_handle) {
    return AVRC_RemoveRecord(sdp_handle);
  }

  uint16_t FindService(uint16_t service_uuid, const RawAddress& bd_addr,
                       tAVRC_SDP_DB_PARAMS* p_db,
                       tAVRC_FIND_CBACK p_cback) override {
    return AVRC_FindService(service_uuid, bd_addr, p_db, p_cback);
  }

  uint16_t Open(uint8_t* p_handle, tAVRC_CONN_CB* p_ccb,
                const RawAddress& bd_addr) override {
    return AVRC_Open(p_handle, p_ccb, bd_addr);
  }

  uint16_t OpenBrowse(uint8_t handle, uint8_t conn_role) override {
    return AVRC_OpenBrowse(handle, conn_role);
  }

  uint16_t GetPeerMtu(uint8_t handle) override {
    return AVCT_GetPeerMtu(handle);
  }

  uint16_t GetBrowseMtu(uint8_t handle) override {
    return AVCT_GetBrowseMtu(handle);
  }

  uint16_t Close(uint8_t handle) override { return AVRC_Close(handle); }

  uint16_t CloseBrowse(uint8_t handle) override {
    return AVRC_CloseBrowse(handle);
  }

  uint16_t MsgReq(uint8_t handle, uint8_t label, uint8_t ctype,
                  BT_HDR* p_pkt) override {
    return AVRC_MsgReq(handle, label, ctype, p_pkt);
  }
} avrcp_interface_;

class SdpInterfaceImpl : public SdpInterface {
 public:
  bool InitDiscoveryDb(tSDP_DISCOVERY_DB* a, uint32_t b, uint16_t c,
                       const bluetooth::Uuid* d, uint16_t e,
                       uint16_t* f) override {
    return SDP_InitDiscoveryDb(a, b, c, d, e, f);
  }

  bool ServiceSearchAttributeRequest(const RawAddress& a, tSDP_DISCOVERY_DB* b,
                                     tSDP_DISC_CMPL_CB* c) override {
    return SDP_ServiceSearchAttributeRequest(a, b, c);
  }

  tSDP_DISC_REC* FindServiceInDb(tSDP_DISCOVERY_DB* a, uint16_t b,
                                 t_sdp_disc_rec* c) override {
    return SDP_FindServiceInDb(a, b, c);
  }

  tSDP_DISC_ATTR* FindAttributeInRec(t_sdp_disc_rec* a, uint16_t b) override {
    return SDP_FindAttributeInRec(a, b);
  }

  bool FindProfileVersionInRec(t_sdp_disc_rec* a, uint16_t b,
                               uint16_t* c) override {
    return SDP_FindProfileVersionInRec(a, b, c);
  }
} sdp_interface_;

// A wrapper class for the media callbacks that handles thread
// switching/synchronization so the devices don't have to worry about it.
class MediaInterfaceWrapper : public MediaInterface {
 public:
  MediaInterfaceWrapper(MediaInterface* cb) : wrapped_(cb){};

  void SendKeyEvent(uint8_t key, KeyState state) override {
    do_in_avrcp_jni(base::Bind(&MediaInterface::SendKeyEvent,
                               base::Unretained(wrapped_), key, state));
  }

  void GetSongInfo(SongInfoCallback info_cb) override {
    auto cb_lambda = [](SongInfoCallback cb, SongInfo data) {
      do_in_main_thread(FROM_HERE, base::Bind(cb, data));
    };

    auto bound_cb = base::Bind(cb_lambda, info_cb);

    do_in_avrcp_jni(base::Bind(&MediaInterface::GetSongInfo,
                               base::Unretained(wrapped_), bound_cb));
  }

  void GetPlayStatus(PlayStatusCallback status_cb) override {
    auto cb_lambda = [](PlayStatusCallback cb, PlayStatus status) {
      do_in_main_thread(FROM_HERE, base::Bind(cb, status));
    };

    auto bound_cb = base::Bind(cb_lambda, status_cb);

    do_in_avrcp_jni(base::Bind(&MediaInterface::GetPlayStatus,
                               base::Unretained(wrapped_), bound_cb));
  }

  void GetNowPlayingList(NowPlayingCallback now_playing_cb) override {
    auto cb_lambda = [](NowPlayingCallback cb, std::string curr_media_id,
                        std::vector<SongInfo> song_list) {
      do_in_main_thread(FROM_HERE,
                        base::Bind(cb, curr_media_id, std::move(song_list)));
    };

    auto bound_cb = base::Bind(cb_lambda, now_playing_cb);

    do_in_avrcp_jni(base::Bind(&MediaInterface::GetNowPlayingList,
                               base::Unretained(wrapped_), bound_cb));
  }

  void GetMediaPlayerList(MediaListCallback list_cb) override {
    auto cb_lambda = [](MediaListCallback cb, uint16_t curr_player,
                        std::vector<MediaPlayerInfo> player_list) {
      do_in_main_thread(FROM_HERE,
                        base::Bind(cb, curr_player, std::move(player_list)));
    };

    auto bound_cb = base::Bind(cb_lambda, list_cb);

    do_in_avrcp_jni(base::Bind(&MediaInterface::GetMediaPlayerList,
                               base::Unretained(wrapped_), bound_cb));
  }

  void GetFolderItems(uint16_t player_id, std::string media_id,
                      FolderItemsCallback folder_cb) override {
    auto cb_lambda = [](FolderItemsCallback cb,
                        std::vector<ListItem> item_list) {
      do_in_main_thread(FROM_HERE, base::Bind(cb, std::move(item_list)));
    };

    auto bound_cb = base::Bind(cb_lambda, folder_cb);

    do_in_avrcp_jni(base::Bind(&MediaInterface::GetFolderItems,
                               base::Unretained(wrapped_), player_id, media_id,
                               bound_cb));
  }

  void SetBrowsedPlayer(uint16_t player_id,
                        SetBrowsedPlayerCallback browse_cb) override {
    auto cb_lambda = [](SetBrowsedPlayerCallback cb, bool success,
                        std::string root_id, uint32_t num_items) {
      do_in_main_thread(FROM_HERE, base::Bind(cb, success, root_id, num_items));
    };

    auto bound_cb = base::Bind(cb_lambda, browse_cb);

    do_in_avrcp_jni(base::Bind(&MediaInterface::SetBrowsedPlayer,
                               base::Unretained(wrapped_), player_id,
                               bound_cb));
  }

  void PlayItem(uint16_t player_id, bool now_playing,
                std::string media_id) override {
    do_in_avrcp_jni(base::Bind(&MediaInterface::PlayItem,
                               base::Unretained(wrapped_), player_id,
                               now_playing, media_id));
  }

  void SetActiveDevice(const RawAddress& address) override {
    do_in_avrcp_jni(base::Bind(&MediaInterface::SetActiveDevice,
                               base::Unretained(wrapped_), address));
  }

  void RegisterUpdateCallback(MediaCallbacks* callback) override {
    wrapped_->RegisterUpdateCallback(callback);
  }

  void UnregisterUpdateCallback(MediaCallbacks* callback) override {
    wrapped_->UnregisterUpdateCallback(callback);
  }

 private:
  MediaInterface* wrapped_;
};

// A wrapper class for the media callbacks that handles thread
// switching/synchronization so the devices don't have to worry about it.
class VolumeInterfaceWrapper : public VolumeInterface {
 public:
  VolumeInterfaceWrapper(VolumeInterface* interface) : wrapped_(interface){};

  void DeviceConnected(const RawAddress& bdaddr) override {
    do_in_avrcp_jni(
        base::Bind(static_cast<void (VolumeInterface::*)(const RawAddress&)>(
                       &VolumeInterface::DeviceConnected),
                   base::Unretained(wrapped_), bdaddr));
  }

  void DeviceConnected(const RawAddress& bdaddr, VolumeChangedCb cb) override {
    auto cb_lambda = [](VolumeChangedCb cb, int8_t volume) {
      do_in_main_thread(FROM_HERE, base::Bind(cb, volume));
    };

    auto bound_cb = base::Bind(cb_lambda, cb);

    do_in_avrcp_jni(base::Bind(static_cast<void (VolumeInterface::*)(
                                   const RawAddress&, VolumeChangedCb)>(
                                   &VolumeInterface::DeviceConnected),
                               base::Unretained(wrapped_), bdaddr, bound_cb));
  }

  void DeviceDisconnected(const RawAddress& bdaddr) override {
    do_in_avrcp_jni(base::Bind(&VolumeInterface::DeviceDisconnected,
                               base::Unretained(wrapped_), bdaddr));
  }

  void SetVolume(int8_t volume) override {
    do_in_avrcp_jni(base::Bind(&VolumeInterface::SetVolume,
                               base::Unretained(wrapped_), volume));
  }

 private:
  VolumeInterface* wrapped_;
};

void AvrcpService::Init(MediaInterface* media_interface,
                        VolumeInterface* volume_interface) {
  LOG(INFO) << "AVRCP Target Service started";

  profile_version = avrcp_interface_.GetAvrcpVersion();

  uint16_t supported_features = GetSupportedFeatures(profile_version);
  sdp_record_handle = SDP_CreateRecord();

  avrcp_interface_.AddRecord(UUID_SERVCLASS_AV_REM_CTRL_TARGET,
                             "AV Remote Control Target", NULL,
                             supported_features, sdp_record_handle, true,
                             profile_version, 0);
  btif_dm_add_uuid_to_eir(UUID_SERVCLASS_AV_REM_CTRL_TARGET);

  media_interface_ = new MediaInterfaceWrapper(media_interface);
  media_interface->RegisterUpdateCallback(instance_);

  VolumeInterfaceWrapper* wrapped_volume_interface = nullptr;
  if (volume_interface != nullptr) {
    wrapped_volume_interface = new VolumeInterfaceWrapper(volume_interface);
  }

  volume_interface_ = wrapped_volume_interface;

  ConnectionHandler::Initialize(
      base::Bind(&AvrcpService::DeviceCallback, base::Unretained(instance_)),
      &avrcp_interface_, &sdp_interface_, wrapped_volume_interface);
  connection_handler_ = ConnectionHandler::Get();
}

uint16_t AvrcpService::GetSupportedFeatures(uint16_t profile_version) {
  switch (profile_version) {
    case AVRC_REV_1_6:
      return AVRCP_SUPF_TG_1_6;
    case AVRC_REV_1_5:
      return AVRCP_SUPF_TG_1_5;
    case AVRC_REV_1_4:
      return AVRCP_SUPF_TG_1_4;
    case AVRC_REV_1_3:
      return AVRCP_SUPF_TG_1_3;
  }
  return AVRCP_SUPF_TG_DEFAULT;
}

void AvrcpService::Cleanup() {
  LOG(INFO) << "AVRCP Target Service stopped";

  avrcp_interface_.RemoveRecord(sdp_record_handle);
  btif_dm_remove_uuid_from_eir(UUID_SERVCLASS_AV_REM_CTRL_TARGET);
  sdp_record_handle = -1;

  connection_handler_->CleanUp();
  connection_handler_ = nullptr;
  if (volume_interface_ != nullptr) {
    delete volume_interface_;
  }
  delete media_interface_;
}

void AvrcpService::RegisterBipServer(int psm) {
  LOG(INFO) << "AVRCP Target Service has registered a BIP OBEX server, psm="
            << psm;
  avrcp_interface_.RemoveRecord(sdp_record_handle);
  uint16_t supported_features
      = GetSupportedFeatures(profile_version) | AVRC_SUPF_TG_PLAYER_COVER_ART;
  sdp_record_handle = SDP_CreateRecord();
  avrcp_interface_.AddRecord(UUID_SERVCLASS_AV_REM_CTRL_TARGET,
                             "AV Remote Control Target", NULL,
                             supported_features, sdp_record_handle, true,
                             profile_version, psm);
}

void AvrcpService::UnregisterBipServer() {
  LOG(INFO) << "AVRCP Target Service has unregistered a BIP OBEX server";
  avrcp_interface_.RemoveRecord(sdp_record_handle);
  uint16_t supported_features = GetSupportedFeatures(profile_version);
  sdp_record_handle = SDP_CreateRecord();
  avrcp_interface_.AddRecord(UUID_SERVCLASS_AV_REM_CTRL_TARGET,
                             "AV Remote Control Target", NULL,
                             supported_features, sdp_record_handle, true,
                             profile_version, 0);
}

AvrcpService* AvrcpService::Get() {
  CHECK(instance_);
  return instance_;
}

ServiceInterface* AvrcpService::GetServiceInterface() {
  if (service_interface_ == nullptr) {
    service_interface_ = new ServiceInterfaceImpl();
  }

  return service_interface_;
}

void AvrcpService::ConnectDevice(const RawAddress& bdaddr) {
  LOG(INFO) << __PRETTY_FUNCTION__ << ": address=" << bdaddr.ToString();

  connection_handler_->ConnectDevice(bdaddr);
}

void AvrcpService::DisconnectDevice(const RawAddress& bdaddr) {
  LOG(INFO) << __PRETTY_FUNCTION__ << ": address=" << bdaddr.ToString();
  connection_handler_->DisconnectDevice(bdaddr);
}

void AvrcpService::SetBipClientStatus(const RawAddress& bdaddr,
                                      bool connected) {
  LOG(INFO) << __PRETTY_FUNCTION__ << ": address=" << bdaddr.ToString()
            << ", connected=" << connected;
  connection_handler_->SetBipClientStatus(bdaddr, connected);
}

void AvrcpService::SendMediaUpdate(bool track_changed, bool play_state,
                                   bool queue) {
  LOG(INFO) << __PRETTY_FUNCTION__ << " track_changed=" << track_changed
            << " : "
            << " play_state=" << play_state << " : "
            << " queue=" << queue;

  // This function may be called on any thread, we need to make sure that the
  // device update happens on the main thread.
  for (const auto& device :
       instance_->connection_handler_->GetListOfDevices()) {
    do_in_main_thread(FROM_HERE,
                      base::Bind(&Device::SendMediaUpdate, device.get()->Get(), track_changed, play_state, queue));
  }
}

void AvrcpService::SendFolderUpdate(bool available_players,
                                    bool addressed_players, bool uids) {
  LOG(INFO) << __PRETTY_FUNCTION__ << " available_players=" << available_players
            << " : "
            << " addressed_players=" << addressed_players << " : "
            << " uids=" << uids;

  // Ensure that the update is posted to the correct thread
  for (const auto& device :
       instance_->connection_handler_->GetListOfDevices()) {
    do_in_main_thread(FROM_HERE, base::Bind(&Device::SendFolderUpdate, device.get()->Get(), available_players,
                                            addressed_players, uids));
  }
}

// Send out the track changed info to update the playback state for each device
void AvrcpService::SendActiveDeviceChanged(const RawAddress& address) {
  SendMediaUpdate(false, true, false);
}

void AvrcpService::DeviceCallback(std::shared_ptr<Device> new_device) {
  if (new_device == nullptr) return;

  // TODO (apanicke): Pass the interfaces into the connection handler
  // so that the devices can be created with any interfaces they need.
  new_device->RegisterInterfaces(media_interface_, &a2dp_interface_,
                                 volume_interface_);
}

// Service Interface
void AvrcpService::ServiceInterfaceImpl::Init(
    MediaInterface* media_interface, VolumeInterface* volume_interface) {
  std::lock_guard<std::mutex> lock(service_interface_lock_);

  // TODO: This function should block until the service is completely up so
  // that its possible to call Get() on the service immediately after calling
  // init without issues.

  CHECK(instance_ == nullptr);
  instance_ = new AvrcpService();

  do_in_main_thread(FROM_HERE,
                    base::Bind(&AvrcpService::Init, base::Unretained(instance_),
                               media_interface, volume_interface));
}

void AvrcpService::ServiceInterfaceImpl::RegisterBipServer(int psm) {
  std::lock_guard<std::mutex> lock(service_interface_lock_);
  CHECK(instance_ != nullptr);
  do_in_main_thread(FROM_HERE, base::Bind(&AvrcpService::RegisterBipServer,
                                          base::Unretained(instance_), psm));
}

void AvrcpService::ServiceInterfaceImpl::UnregisterBipServer() {
  std::lock_guard<std::mutex> lock(service_interface_lock_);
  CHECK(instance_ != nullptr);
  do_in_main_thread(FROM_HERE, base::Bind(&AvrcpService::UnregisterBipServer,
                                          base::Unretained(instance_)));
}

bool AvrcpService::ServiceInterfaceImpl::ConnectDevice(
    const RawAddress& bdaddr) {
  std::lock_guard<std::mutex> lock(service_interface_lock_);
  CHECK(instance_ != nullptr);
  do_in_main_thread(FROM_HERE, base::Bind(&AvrcpService::ConnectDevice,
                                          base::Unretained(instance_), bdaddr));
  return true;
}

bool AvrcpService::ServiceInterfaceImpl::DisconnectDevice(
    const RawAddress& bdaddr) {
  std::lock_guard<std::mutex> lock(service_interface_lock_);
  CHECK(instance_ != nullptr);
  do_in_main_thread(FROM_HERE, base::Bind(&AvrcpService::DisconnectDevice,
                                          base::Unretained(instance_), bdaddr));
  return true;
}

void AvrcpService::ServiceInterfaceImpl::SetBipClientStatus(
    const RawAddress& bdaddr, bool connected) {
  std::lock_guard<std::mutex> lock(service_interface_lock_);
  CHECK(instance_ != nullptr);
  do_in_main_thread(FROM_HERE, base::Bind(&AvrcpService::SetBipClientStatus,
                                          base::Unretained(instance_), bdaddr,
                                          connected));
}

bool AvrcpService::ServiceInterfaceImpl::Cleanup() {
  std::lock_guard<std::mutex> lock(service_interface_lock_);

  if (instance_ == nullptr) return false;

  do_in_main_thread(FROM_HERE,
                    base::Bind(&AvrcpService::Cleanup, base::Owned(instance_)));

  // Setting instance to nullptr here is fine since it will be deleted on the
  // other thread.
  instance_ = nullptr;

  return true;
}

void AvrcpService::DebugDump(int fd) {
  if (instance_ == nullptr) {
    dprintf(fd, "\nAVRCP Target Service not started\n");
    return;
  }

  auto device_list = instance_->connection_handler_->GetListOfDevices();
  dprintf(fd, "\nAVRCP Target Native Service: %zu devices\n",
          device_list.size());

  std::stringstream stream;
  {
    ScopedIndent indent(stream);
    for (const auto& device : device_list) {
      stream << *device << std::endl;
    }
  }

  dprintf(fd, "%s", stream.str().c_str());
}

}  // namespace avrcp
}  // namespace bluetooth
