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

namespace bluetooth {
namespace avrcp {

std::unique_ptr<GetFolderItemsResponseBuilder>
GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status status,
                                                     uint16_t uid_counter,
                                                     size_t mtu) {
  std::unique_ptr<GetFolderItemsResponseBuilder> builder(
      new GetFolderItemsResponseBuilder(Scope::MEDIA_PLAYER_LIST, status,
                                        uid_counter, mtu));

  return builder;
}

std::unique_ptr<GetFolderItemsResponseBuilder>
GetFolderItemsResponseBuilder::MakeVFSBuilder(Status status,
                                              uint16_t uid_counter,
                                              size_t mtu) {
  std::unique_ptr<GetFolderItemsResponseBuilder> builder(
      new GetFolderItemsResponseBuilder(Scope::VFS, status, uid_counter, mtu));

  return builder;
}

std::unique_ptr<GetFolderItemsResponseBuilder>
GetFolderItemsResponseBuilder::MakeNowPlayingBuilder(Status status,
                                                     uint16_t uid_counter,
                                                     size_t mtu) {
  std::unique_ptr<GetFolderItemsResponseBuilder> builder(
      new GetFolderItemsResponseBuilder(Scope::NOW_PLAYING, status, uid_counter,
                                        mtu));

  return builder;
}

size_t GetFolderItemsResponseBuilder::size() const {
  size_t len = BrowsePacket::kMinSize();
  len += 1;  // Status

  // There is nothing other than the status in the packet if the status isn't
  // NO_ERROR
  if (status_ != Status::NO_ERROR || items_.size() == 0) return len;

  len += 2;  // UID Counter
  len += 2;  // Number of Items;
  for (const auto& item : items_) {
    len += item.size();
  }

  return len;
}

bool GetFolderItemsResponseBuilder::Serialize(
    const std::shared_ptr<::bluetooth::Packet>& pkt) {
  ReserveSpace(pkt, size());

  BrowsePacketBuilder::PushHeader(pkt, size() - BrowsePacket::kMinSize());

  if (status_ == Status::NO_ERROR && items_.size() == 0) {
    // Return range out of bounds if there are zero items in the folder
    status_ = Status::RANGE_OUT_OF_BOUNDS;
  }

  AddPayloadOctets1(pkt, (uint8_t)status_);  // Status
  if (status_ != Status::NO_ERROR) return true;

  AddPayloadOctets2(pkt, base::ByteSwap(uid_counter_));
  uint16_t num_items = items_.size();
  AddPayloadOctets2(pkt, base::ByteSwap(num_items));

  for (const auto& item : items_) {
    PushMediaListItem(pkt, item);
  }

  return true;
}

bool GetFolderItemsResponseBuilder::AddMediaPlayer(MediaPlayerItem item) {
  CHECK(scope_ == Scope::MEDIA_PLAYER_LIST);

  if (size() + item.size() > mtu_) return false;

  items_.push_back(MediaListItem(item));
  return true;
}

bool GetFolderItemsResponseBuilder::AddSong(MediaElementItem item) {
  CHECK(scope_ == Scope::VFS || scope_ == Scope::NOW_PLAYING);

  if (size() + item.size() > mtu_) return false;

  items_.push_back(MediaListItem(item));
  return true;
}

bool GetFolderItemsResponseBuilder::AddFolder(FolderItem item) {
  CHECK(scope_ == Scope::VFS);

  if (size() + item.size() > mtu_) return false;

  items_.push_back(MediaListItem(item));
  return true;
}

void GetFolderItemsResponseBuilder::PushMediaListItem(
    const std::shared_ptr<::bluetooth::Packet>& pkt,
    const MediaListItem& item) {
  switch (item.type_) {
    case MediaListItem::PLAYER:
      PushMediaPlayerItem(pkt, item.player_);
      break;
    case MediaListItem::FOLDER:
      PushFolderItem(pkt, item.folder_);
      break;
    case MediaListItem::SONG:
      PushMediaElementItem(pkt, item.song_);
      break;
  }
}

void GetFolderItemsResponseBuilder::PushMediaPlayerItem(
    const std::shared_ptr<::bluetooth::Packet>& pkt,
    const MediaPlayerItem& item) {
  AddPayloadOctets1(pkt, 0x01);  // Media Player Item
  uint16_t item_len = item.size() - 3;
  AddPayloadOctets2(pkt, base::ByteSwap(item_len));  // Item length
  AddPayloadOctets2(pkt, base::ByteSwap(item.id_));  // Player ID
  AddPayloadOctets1(pkt, 0x01);                      // Player Type
  AddPayloadOctets4(pkt, 0x00000000);                // Player Subtype
  AddPayloadOctets1(
      pkt, 0x02);  // Player Play Status // TODO: Add this as a passed field

  // Features
  AddPayloadOctets1(pkt, 0x00);
  AddPayloadOctets1(pkt, 0x00);
  AddPayloadOctets1(pkt, 0x00);
  AddPayloadOctets1(pkt, 0x00);
  AddPayloadOctets1(pkt, 0x00);
  AddPayloadOctets1(pkt, 0xb7);
  AddPayloadOctets1(pkt, 0x01);
  if (item.browsable_) {
    AddPayloadOctets1(pkt, 0x0C);
    AddPayloadOctets1(pkt, 0x0a);
  } else {
    AddPayloadOctets1(pkt, 0x04);
    AddPayloadOctets1(pkt, 0x00);
  }
  AddPayloadOctets1(pkt, 0x00);
  AddPayloadOctets1(pkt, 0x00);
  AddPayloadOctets1(pkt, 0x00);
  AddPayloadOctets1(pkt, 0x00);
  AddPayloadOctets1(pkt, 0x00);
  AddPayloadOctets1(pkt, 0x00);
  AddPayloadOctets1(pkt, 0x00);

  AddPayloadOctets2(pkt, base::ByteSwap((uint16_t)0x006a));
  uint16_t name_len = item.name_.size();
  AddPayloadOctets2(pkt, base::ByteSwap(name_len));

  for (const uint8_t& byte : item.name_) {
    AddPayloadOctets1(pkt, byte);
  }
}

void GetFolderItemsResponseBuilder::PushFolderItem(
    const std::shared_ptr<::bluetooth::Packet>& pkt, const FolderItem& item) {
  AddPayloadOctets1(pkt, 0x02);  // Folder Item
  uint16_t item_len = item.size() - 3;
  AddPayloadOctets2(pkt, base::ByteSwap(item_len));
  AddPayloadOctets8(pkt, base::ByteSwap(item.uid_));
  AddPayloadOctets1(pkt, item.folder_type_);
  AddPayloadOctets1(pkt, item.is_playable_ ? 0x01 : 0x00);
  AddPayloadOctets2(pkt,
                    base::ByteSwap((uint16_t)0x006a));  // UTF-8 Character Set
  uint16_t name_len = item.name_.size();
  AddPayloadOctets2(pkt, base::ByteSwap(name_len));
  for (const uint8_t& byte : item.name_) {
    AddPayloadOctets1(pkt, byte);
  }
}

void GetFolderItemsResponseBuilder::PushMediaElementItem(
    const std::shared_ptr<::bluetooth::Packet>& pkt,
    const MediaElementItem& item) {
  AddPayloadOctets1(pkt, 0x03);  // Media Element Item
  uint16_t item_len = item.size() - 3;
  AddPayloadOctets2(pkt, base::ByteSwap(item_len));
  AddPayloadOctets8(pkt, base::ByteSwap(item.uid_));
  AddPayloadOctets1(pkt, 0x00);  // Media Type Audio
  AddPayloadOctets2(pkt,
                    base::ByteSwap((uint16_t)0x006a));  // UTF-8 Character Set
  uint16_t name_len = item.name_.size();
  AddPayloadOctets2(pkt, base::ByteSwap(name_len));
  for (const uint8_t& byte : item.name_) {
    AddPayloadOctets1(pkt, byte);
  }

  AddPayloadOctets1(pkt, (uint8_t)item.attributes_.size());
  for (const auto& entry : item.attributes_) {
    AddPayloadOctets4(pkt, base::ByteSwap((uint32_t)entry.attribute()));
    AddPayloadOctets2(pkt,
                      base::ByteSwap((uint16_t)0x006a));  // UTF-8 Character Set

    std::string attr_val = entry.value();
    uint16_t attr_len = attr_val.size();

    AddPayloadOctets2(pkt, base::ByteSwap(attr_len));
    for (const uint8_t& byte : attr_val) {
      AddPayloadOctets1(pkt, byte);
    }
  }
}

Scope GetFolderItemsRequest::GetScope() const {
  auto it = begin() + BrowsePacket::kMinSize();
  return static_cast<Scope>(*it);
}

uint32_t GetFolderItemsRequest::GetStartItem() const {
  auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(1);
  return base::ByteSwap(it.extract<uint32_t>());
}

uint32_t GetFolderItemsRequest::GetEndItem() const {
  auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(5);
  return base::ByteSwap(it.extract<uint32_t>());
}

uint8_t GetFolderItemsRequest::GetNumAttributes() const {
  auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(9);
  return *it;
}

std::vector<Attribute> GetFolderItemsRequest::GetAttributesRequested() const {
  auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(9);

  size_t number_of_attributes = it.extract<uint8_t>();
  std::vector<Attribute> attribute_list;

  // No attributes requested
  if (number_of_attributes == 0xFF) return attribute_list;

  // TODO: If the number of attributes equals 0, then all attributes are
  // requested right now thats handled in the service itself, but it'd be nice
  // to have this function return a vector with all the attributes

  for (size_t i = 0; i < number_of_attributes; i++) {
    attribute_list.push_back((Attribute)base::ByteSwap(it.extract<uint32_t>()));
  }

  return attribute_list;
}

bool GetFolderItemsRequest::IsValid() const {
  if (!BrowsePacket::IsValid()) return false;
  // The minimum size required to be valid
  if (size() < kMinSize()) return false;

  auto attr_count = GetNumAttributes();

  // No items requested
  if (attr_count == 0xFF) return true;

  auto attr_start = begin() + kMinSize();

  // Casting the int returned from end - attr_start should be fine. If an
  // overflow occurs we can definitly say the packet is invalid
  return (attr_count * sizeof(Attribute)) == (size_t)(end() - attr_start);
}

std::string GetFolderItemsRequest::ToString() const {
  std::stringstream ss;
  ss << "GetFolderItemsRequestPacket: " << std::endl;
  ss << "  └ PDU = " << GetPdu() << std::endl;
  ss << "  └ Length = " << GetLength() << std::endl;
  ss << "  └ Scope = " << GetScope() << std::endl;
  ss << "  └ Start Item = " << loghex(GetStartItem()) << std::endl;
  ss << "  └ End Item = " << loghex(GetEndItem()) << std::endl;
  ss << "  └ Attribute Count = " << loghex(GetNumAttributes()) << std::endl;

  ss << std::endl;

  return ss.str();
}

std::unique_ptr<GetFolderItemsRequestBuilder>
GetFolderItemsRequestBuilder::MakeBuilder(
    Scope scope, uint32_t start_item, uint32_t end_item,
    const std::set<Attribute>& requested_attrs) {
  std::unique_ptr<GetFolderItemsRequestBuilder> builder(
      new GetFolderItemsRequestBuilder(scope, start_item, end_item,
                                       requested_attrs));

  return builder;
}

size_t GetFolderItemsRequestBuilder::size() const {
  size_t len = GetFolderItemsRequest::kMinSize();
  len += requested_attrs_.size() * sizeof(Attribute);
  return len;
}

bool GetFolderItemsRequestBuilder::Serialize(
    const std::shared_ptr<::bluetooth::Packet>& pkt) {
  ReserveSpace(pkt, size());

  BrowsePacketBuilder::PushHeader(pkt, size() - BrowsePacket::kMinSize());

  AddPayloadOctets1(pkt, static_cast<uint8_t>(scope_));
  AddPayloadOctets4(pkt, base::ByteSwap(start_item_));
  AddPayloadOctets4(pkt, base::ByteSwap(end_item_));

  if (requested_attrs_.size() == 0) {
    // 0xFF is the value to signify that there are no attributes requested.
    AddPayloadOctets1(pkt, 0xFF);
    return true;
  }

  AddPayloadOctets1(pkt, requested_attrs_.size());
  for (const auto& attr : requested_attrs_) {
    AddPayloadOctets4(pkt, base::ByteSwap(static_cast<uint32_t>(attr)));
  }
  return true;
}

}  // namespace avrcp
}  // namespace bluetooth