/*
 * Copyright 2020 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 "hci/acl_manager/round_robin_scheduler.h"
#include "hci/acl_manager/acl_fragmenter.h"

namespace bluetooth {
namespace hci {
namespace acl_manager {

RoundRobinScheduler::RoundRobinScheduler(
    os::Handler* handler, Controller* controller, common::BidiQueueEnd<AclBuilder, AclView>* hci_queue_end)
    : handler_(handler), controller_(controller), hci_queue_end_(hci_queue_end) {
  max_acl_packet_credits_ = controller_->GetNumAclPacketBuffers();
  acl_packet_credits_ = max_acl_packet_credits_;
  hci_mtu_ = controller_->GetAclPacketLength();
  LeBufferSize le_buffer_size = controller_->GetLeBufferSize();
  le_max_acl_packet_credits_ = le_buffer_size.total_num_le_packets_;
  le_acl_packet_credits_ = le_max_acl_packet_credits_;
  le_hci_mtu_ = le_buffer_size.le_data_packet_length_;
  controller_->RegisterCompletedAclPacketsCallback(handler->BindOn(this, &RoundRobinScheduler::incoming_acl_credits));
}

RoundRobinScheduler::~RoundRobinScheduler() {
  unregister_all_connections();
  controller_->UnregisterCompletedAclPacketsCallback();
}

void RoundRobinScheduler::Register(ConnectionType connection_type, uint16_t handle,
                                   std::shared_ptr<acl_manager::AclConnection::Queue> queue) {
  acl_queue_handler acl_queue_handler = {connection_type, std::move(queue), false, 0};
  acl_queue_handlers_.insert(std::pair<uint16_t, RoundRobinScheduler::acl_queue_handler>(handle, acl_queue_handler));
  if (fragments_to_send_.size() == 0) {
    start_round_robin();
  }
}

void RoundRobinScheduler::Unregister(uint16_t handle) {
  ASSERT(acl_queue_handlers_.count(handle) == 1);
  auto acl_queue_handler = acl_queue_handlers_.find(handle)->second;
  // Reclaim outstanding packets
  if (acl_queue_handler.connection_type_ == ConnectionType::CLASSIC) {
    acl_packet_credits_ += acl_queue_handler.number_of_sent_packets_;
  } else {
    le_acl_packet_credits_ += acl_queue_handler.number_of_sent_packets_;
  }
  acl_queue_handler.number_of_sent_packets_ = 0;

  if (acl_queue_handler.dequeue_is_registered_) {
    acl_queue_handler.dequeue_is_registered_ = false;
    acl_queue_handler.queue_->GetDownEnd()->UnregisterDequeue();
  }
  acl_queue_handlers_.erase(handle);
  starting_point_ = acl_queue_handlers_.begin();
}

void RoundRobinScheduler::SetLinkPriority(uint16_t handle, bool high_priority) {
  auto acl_queue_handler = acl_queue_handlers_.find(handle);
  if (acl_queue_handler == acl_queue_handlers_.end()) {
    LOG_WARN("handle %d is invalid", handle);
    return;
  }
  acl_queue_handler->second.high_priority_ = high_priority;
}

uint16_t RoundRobinScheduler::GetCredits() {
  return acl_packet_credits_;
}

uint16_t RoundRobinScheduler::GetLeCredits() {
  return le_acl_packet_credits_;
}

void RoundRobinScheduler::start_round_robin() {
  if (acl_packet_credits_ == 0 && le_acl_packet_credits_ == 0) {
    return;
  }
  if (!fragments_to_send_.empty()) {
    auto connection_type = fragments_to_send_.front().first;
    bool classic_buffer_full = acl_packet_credits_ == 0 && connection_type == ConnectionType::CLASSIC;
    bool le_buffer_full = le_acl_packet_credits_ == 0 && connection_type == ConnectionType::LE;
    if (classic_buffer_full || le_buffer_full) {
      LOG_WARN("Buffer of connection_type %d is full", connection_type);
      return;
    }
    send_next_fragment();
    return;
  }
  if (acl_queue_handlers_.empty()) {
    LOG_INFO("No any acl connection");
    return;
  }

  if (acl_queue_handlers_.size() == 1 || starting_point_ == acl_queue_handlers_.end()) {
    starting_point_ = acl_queue_handlers_.begin();
  }
  size_t count = acl_queue_handlers_.size();

  for (auto acl_queue_handler = starting_point_; count > 0; count--) {
    // Prevent registration when credits is zero
    bool classic_buffer_full =
        acl_packet_credits_ == 0 && acl_queue_handler->second.connection_type_ == ConnectionType::CLASSIC;
    bool le_buffer_full =
        le_acl_packet_credits_ == 0 && acl_queue_handler->second.connection_type_ == ConnectionType::LE;
    if (!acl_queue_handler->second.dequeue_is_registered_ && !classic_buffer_full && !le_buffer_full) {
      acl_queue_handler->second.dequeue_is_registered_ = true;
      acl_queue_handler->second.queue_->GetDownEnd()->RegisterDequeue(
          handler_, common::Bind(&RoundRobinScheduler::buffer_packet, common::Unretained(this), acl_queue_handler));
    }
    acl_queue_handler = std::next(acl_queue_handler);
    if (acl_queue_handler == acl_queue_handlers_.end()) {
      acl_queue_handler = acl_queue_handlers_.begin();
    }
  }

  starting_point_ = std::next(starting_point_);
}

void RoundRobinScheduler::buffer_packet(std::map<uint16_t, acl_queue_handler>::iterator acl_queue_handler) {
  BroadcastFlag broadcast_flag = BroadcastFlag::POINT_TO_POINT;
  // Wrap packet and enqueue it
  uint16_t handle = acl_queue_handler->first;
  auto packet = acl_queue_handler->second.queue_->GetDownEnd()->TryDequeue();
  ASSERT(packet != nullptr);

  ConnectionType connection_type = acl_queue_handler->second.connection_type_;
  size_t mtu = connection_type == ConnectionType::CLASSIC ? hci_mtu_ : le_hci_mtu_;
  PacketBoundaryFlag packet_boundary_flag = (packet->IsFlushable())
                                                ? PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE
                                                : PacketBoundaryFlag::FIRST_NON_AUTOMATICALLY_FLUSHABLE;

  int acl_priority = acl_queue_handler->second.high_priority_ ? 1 : 0;
  if (packet->size() <= mtu) {
    fragments_to_send_.push(
        std::make_pair(
            connection_type, AclBuilder::Create(handle, packet_boundary_flag, broadcast_flag, std::move(packet))),
        acl_priority);
  } else {
    auto fragments = AclFragmenter(mtu, std::move(packet)).GetFragments();
    for (size_t i = 0; i < fragments.size(); i++) {
      fragments_to_send_.push(
          std::make_pair(
              connection_type,
              AclBuilder::Create(handle, packet_boundary_flag, broadcast_flag, std::move(fragments[i]))),
          acl_priority);
      packet_boundary_flag = PacketBoundaryFlag::CONTINUING_FRAGMENT;
    }
  }
  ASSERT(fragments_to_send_.size() > 0);
  unregister_all_connections();

  acl_queue_handler->second.number_of_sent_packets_ += fragments_to_send_.size();
  send_next_fragment();
}

void RoundRobinScheduler::unregister_all_connections() {
  for (auto acl_queue_handler = acl_queue_handlers_.begin(); acl_queue_handler != acl_queue_handlers_.end();
       acl_queue_handler = std::next(acl_queue_handler)) {
    if (acl_queue_handler->second.dequeue_is_registered_) {
      acl_queue_handler->second.dequeue_is_registered_ = false;
      acl_queue_handler->second.queue_->GetDownEnd()->UnregisterDequeue();
    }
  }
}

void RoundRobinScheduler::send_next_fragment() {
  if (!enqueue_registered_.exchange(true)) {
    hci_queue_end_->RegisterEnqueue(
        handler_, common::Bind(&RoundRobinScheduler::handle_enqueue_next_fragment, common::Unretained(this)));
  }
}

// Invoked from some external Queue Reactable context 1
std::unique_ptr<AclBuilder> RoundRobinScheduler::handle_enqueue_next_fragment() {
  ConnectionType connection_type = fragments_to_send_.front().first;
  if (connection_type == ConnectionType::CLASSIC) {
    ASSERT(acl_packet_credits_ > 0);
    acl_packet_credits_ -= 1;
  } else {
    ASSERT(le_acl_packet_credits_ > 0);
    le_acl_packet_credits_ -= 1;
  }

  auto raw_pointer = fragments_to_send_.front().second.release();
  fragments_to_send_.pop();
  if (fragments_to_send_.empty()) {
    if (enqueue_registered_.exchange(false)) {
      hci_queue_end_->UnregisterEnqueue();
    }
    handler_->Post(common::BindOnce(&RoundRobinScheduler::start_round_robin, common::Unretained(this)));
  } else {
    ConnectionType next_connection_type = fragments_to_send_.front().first;
    bool classic_buffer_full = next_connection_type == ConnectionType::CLASSIC && acl_packet_credits_ == 0;
    bool le_buffer_full = next_connection_type == ConnectionType::LE && le_acl_packet_credits_ == 0;
    if ((classic_buffer_full || le_buffer_full) && enqueue_registered_.exchange(false)) {
      hci_queue_end_->UnregisterEnqueue();
    }
  }
  return std::unique_ptr<AclBuilder>(raw_pointer);
}

void RoundRobinScheduler::incoming_acl_credits(uint16_t handle, uint16_t credits) {
  auto acl_queue_handler = acl_queue_handlers_.find(handle);
  if (acl_queue_handler == acl_queue_handlers_.end()) {
    return;
  }

  if (acl_queue_handler->second.number_of_sent_packets_ >= credits) {
    acl_queue_handler->second.number_of_sent_packets_ -= credits;
  } else {
    LOG_WARN("receive more credits than we sent");
    acl_queue_handler->second.number_of_sent_packets_ = 0;
  }

  bool credit_was_zero = false;
  if (acl_queue_handler->second.connection_type_ == ConnectionType::CLASSIC) {
    if (acl_packet_credits_ == 0) {
      credit_was_zero = true;
    }
    acl_packet_credits_ += credits;
    if (acl_packet_credits_ > max_acl_packet_credits_) {
      acl_packet_credits_ = max_acl_packet_credits_;
      LOG_WARN("acl packet credits overflow due to receive %hx credits", credits);
    }
  } else {
    if (le_acl_packet_credits_ == 0) {
      credit_was_zero = true;
    }
    le_acl_packet_credits_ += credits;
    if (le_acl_packet_credits_ > le_max_acl_packet_credits_) {
      le_acl_packet_credits_ = le_max_acl_packet_credits_;
      LOG_WARN("le acl packet credits overflow due to receive %hx credits", credits);
    }
  }
  if (credit_was_zero) {
    start_round_robin();
  }
}

}  // namespace acl_manager
}  // namespace hci
}  // namespace bluetooth
