//
//  Copyright 2017 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/avrcp_control.h"

#include <base/logging.h>
#include <base/memory/ptr_util.h>
#include <base/strings/string_number_conversions.h>

#include <cerrno>
#include <climits>
#include <string>

#include "notreached.h"
#include "service/logging_helpers.h"
#include "stack/include/avrc_defs.h"
#include "types/raw_address.h"

namespace bluetooth {

AvrcpControl::AvrcpControl(const Uuid& uuid, int control_id)
    : app_identifier_(uuid), control_id_(control_id) {
  hal::BluetoothAvrcpInterface::Get()->AddControlObserver(this);
}

AvrcpControl::~AvrcpControl() {
  hal::BluetoothAvrcpInterface::Get()->RemoveControlObserver(this);
}

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

int AvrcpControl::GetInstanceId() const { return control_id_; }

void AvrcpControl::SetDelegate(Delegate* delegate) {
  std::lock_guard<std::mutex> lock(delegate_mutex_);
  delegate_ = delegate;
}

bool AvrcpControl::Enable() {
  std::lock_guard<std::mutex> lock(mutex_);
  return hal::BluetoothAvrcpInterface::Get()->AvrcpControlEnable();
}

void AvrcpControl::Disable() {
  std::lock_guard<std::mutex> lock(mutex_);
  hal::BluetoothAvrcpInterface::Get()->AvrcpControlDisable();
}

bool AvrcpControl::SendPassThroughCommand(const std::string& device_address,
                                          uint8_t key_code, bool key_pressed) {
  RawAddress addr;
  if (!RawAddress::FromString(device_address, addr)) {
    LOG(ERROR) << "Invalid device address given: " << device_address;
    return false;
  }

  uint8_t key_state = key_pressed ? AVRC_STATE_PRESS : AVRC_STATE_RELEASE;
  bt_status_t status;
  {
    std::lock_guard<std::mutex> lock(mutex_);
    status = hal::BluetoothAvrcpInterface::Get()
                 ->GetControlHALInterface()
                 ->send_pass_through_cmd(addr, key_code, key_state);
  }
  if (status != BT_STATUS_SUCCESS) {
    LOG(ERROR) << "Failed to send passthrough command";
    return false;
  }

  return true;
}

bool AvrcpControl::SetAbsVolumeResponse(const std::string& device_address,
                                        int32_t abs_vol, int32_t label) {
  RawAddress addr;
  if (!RawAddress::FromString(device_address, addr)) {
    LOG(ERROR) << "Invalid device address given: " << device_address;
    return false;
  }

  bt_status_t status;
  {
    std::lock_guard<std::mutex> lock(mutex_);
    status = hal::BluetoothAvrcpInterface::Get()
                 ->GetControlHALInterface()
                 ->set_volume_rsp(addr, abs_vol, label);
  }
  if (status != BT_STATUS_SUCCESS) {
    LOG(ERROR) << "Failed to send set absolute volume response";
    return false;
  }

  return true;
}

bool AvrcpControl::RegisterForAbsVolumeCallbackResponse(
    const std::string& device_address, int32_t response_type, int32_t abs_vol,
    int32_t label) {
  RawAddress addr;
  if (!RawAddress::FromString(device_address, addr)) {
    LOG(ERROR) << "Invalid device address given: " << device_address;
    return false;
  }

  bt_status_t status;
  {
    std::lock_guard<std::mutex> lock(mutex_);
    status = hal::BluetoothAvrcpInterface::Get()
                 ->GetControlHALInterface()
                 ->register_abs_vol_rsp(
                     addr, static_cast<btrc_notification_type_t>(response_type),
                     abs_vol, label);
  }
  if (status != BT_STATUS_SUCCESS) {
    LOG(ERROR)
        << "Failed to send send register for absolute volume change callback";
    return false;
  }

  return true;
}

void AvrcpControl::ConnectionStateCallback(bool rc_connect, bool bt_connect,
                                           const RawAddress& bd_addr) {
  std::string device_address = BtAddrString(&bd_addr);
  std::lock_guard<std::mutex> lock(delegate_mutex_);
  if (delegate_)
    delegate_->OnConnectionState(rc_connect, bt_connect, device_address);
}

void AvrcpControl::CtrlSetabsvolCmdCallback(const RawAddress& bd_addr,
                                            uint8_t abs_vol, uint8_t label) {
  std::string device_address = BtAddrString(&bd_addr);
  std::lock_guard<std::mutex> lock(delegate_mutex_);
  if (delegate_)
    delegate_->OnSetAbsVolumeRequest(device_address, abs_vol, label);
}

void AvrcpControl::CtrlRegisternotificationAbsVolCallback(
    const RawAddress& bd_addr, uint8_t label) {
  std::string device_address = BtAddrString(&bd_addr);
  std::lock_guard<std::mutex> lock(delegate_mutex_);
  if (delegate_)
    delegate_->OnRegisterForAbsVolumeCallbackRequest(device_address, label);
}

void AvrcpControl::CtrlTrackChangedCallback(const RawAddress& bd_addr,
                                            uint8_t num_attr,
                                            btrc_element_attr_val_t* p_attrs) {
  std::string device_address = BtAddrString(&bd_addr);

  std::string title;
  std::string artist;
  std::string album;
  std::string genre;
  int track_num = -1;
  int num_tracks = -1;
  int play_time = -1;

  for (size_t i = 0; i < num_attr; ++i) {
    auto attr_text = reinterpret_cast<char*>(p_attrs[i].text);
    switch (p_attrs[i].attr_id) {
      case BTRC_MEDIA_ATTR_ID_TITLE:
        title = attr_text;
        break;
      case BTRC_MEDIA_ATTR_ID_ARTIST:
        artist = attr_text;
        break;
      case BTRC_MEDIA_ATTR_ID_ALBUM:
        album = attr_text;
        break;
      case BTRC_MEDIA_ATTR_ID_TRACK_NUM:
        if (!base::StringToInt(attr_text, &track_num)) {
          LOG(ERROR) << "Failed to parse track number";
        }
        break;
      case BTRC_MEDIA_ATTR_ID_NUM_TRACKS:
        if (!base::StringToInt(attr_text, &num_tracks)) {
          LOG(ERROR) << "Failed to parse number of tracks";
        }
        break;
      case BTRC_MEDIA_ATTR_ID_GENRE:
        genre = attr_text;
        break;
      case BTRC_MEDIA_ATTR_ID_PLAYING_TIME:
        if (!base::StringToInt(attr_text, &play_time)) {
          LOG(ERROR) << "Failed to parse playing time";
        }
        break;
      default:
        NOTREACHED();
    }
  }

  const AvrcpMediaAttr attr(title, artist, album, genre, track_num, num_tracks,
                            play_time);

  std::lock_guard<std::mutex> lock(delegate_mutex_);
  if (delegate_) delegate_->OnTrackChanged(device_address, attr);
}

// AvrcpControlFactory implementation

AvrcpControlFactory::AvrcpControlFactory() = default;
AvrcpControlFactory::~AvrcpControlFactory() = default;

bool AvrcpControlFactory::RegisterInstance(const Uuid& uuid,
                                           const RegisterCallback& callback) {
  VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();

  int control_id = next_control_id_++;
  std::unique_ptr<AvrcpControl> hf_client(new AvrcpControl(uuid, control_id));
  callback(BLE_STATUS_SUCCESS, uuid, std::move(hf_client));
  return true;
}

}  // namespace bluetooth
