// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sequential_command_runner.h"

#include "command_channel.h"
#include "hci.h"
#include "transport.h"

namespace bt::hci {

SequentialCommandRunner::SequentialCommandRunner(async_dispatcher_t* dispatcher,
                                                 fxl::WeakPtr<Transport> transport)
    : dispatcher_(dispatcher),
      transport_(std::move(transport)),
      sequence_number_(0u),
      running_commands_(0u),
      weak_ptr_factory_(this) {
  ZX_DEBUG_ASSERT(dispatcher_);
  ZX_DEBUG_ASSERT(transport_);
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());
}

SequentialCommandRunner::~SequentialCommandRunner() {
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());
}

void SequentialCommandRunner::QueueCommand(std::unique_ptr<CommandPacket> command_packet,
                                           CommandCompleteCallback callback, bool wait) {
  ZX_DEBUG_ASSERT(!status_callback_);
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());
  ZX_DEBUG_ASSERT(sizeof(CommandHeader) <= command_packet->view().size());

  command_queue_.emplace(QueuedCommand{std::move(command_packet), std::move(callback), wait});
}

void SequentialCommandRunner::RunCommands(StatusCallback status_callback) {
  ZX_DEBUG_ASSERT(!status_callback_);
  ZX_DEBUG_ASSERT(status_callback);
  ZX_DEBUG_ASSERT(!command_queue_.empty());
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());

  status_callback_ = std::move(status_callback);
  sequence_number_++;

  TryRunNextQueuedCommand();
}

bool SequentialCommandRunner::IsReady() const {
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());
  return !status_callback_;
}

void SequentialCommandRunner::Cancel() {
  ZX_DEBUG_ASSERT(status_callback_);
  status_callback_(Status(HostError::kCanceled));
  Reset();
}

bool SequentialCommandRunner::HasQueuedCommands() const {
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());
  return !command_queue_.empty();
}

void SequentialCommandRunner::TryRunNextQueuedCommand(Status status) {
  ZX_DEBUG_ASSERT(status_callback_);

  //. If an error occurred or we're done, reset.
  if (!status || (command_queue_.empty() && running_commands_ == 0)) {
    NotifyStatusAndReset(std::move(status));
    return;
  }

  // Wait for the rest of the running commands to finish if we need to.
  if (command_queue_.empty() || (running_commands_ > 0 && command_queue_.front().wait)) {
    return;
  }

  QueuedCommand next = std::move(command_queue_.front());
  command_queue_.pop();

  auto self = weak_ptr_factory_.GetWeakPtr();
  auto command_callback = [self, cmd_cb = std::move(next.callback), seq_no = sequence_number_](
                              auto, const EventPacket& event_packet) {
    auto status = event_packet.ToStatus();
    if (status && event_packet.event_code() == kCommandStatusEventCode) {
      return;
    }

    // TODO(fxbug.dev/641): Allow async commands to be queued.
    ZX_DEBUG_ASSERT(!status || event_packet.event_code() == kCommandCompleteEventCode);

    if (cmd_cb) {
      cmd_cb(event_packet);
    }

    // The sequence could have been cancelled (and a new sequence could have
    // also started). Make sure here that we are in the correct sequence.
    if (!self || !self->status_callback_ || seq_no != self->sequence_number_) {
      return;
    }
    ZX_DEBUG_ASSERT(self->running_commands_ > 0);
    self->running_commands_--;
    self->TryRunNextQueuedCommand(status);
  };

  running_commands_++;
  if (!transport_->command_channel()->SendCommand(std::move(next.packet),
                                                  std::move(command_callback))) {
    NotifyStatusAndReset(Status(HostError::kFailed));
  } else {
    TryRunNextQueuedCommand();
  }
}

void SequentialCommandRunner::Reset() {
  if (!command_queue_.empty()) {
    command_queue_ = {};
  }
  running_commands_ = 0;
  status_callback_ = nullptr;
}

void SequentialCommandRunner::NotifyStatusAndReset(Status status) {
  ZX_DEBUG_ASSERT(status_callback_);
  auto status_cb = std::move(status_callback_);
  Reset();
  status_cb(status);
}

}  // namespace bt::hci
