// Copyright 2019 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 <lib/fidl/llcpp/message.h>
#include <lib/fidl/llcpp/status.h>
#include <lib/fidl/llcpp/transaction.h>

namespace fidl {

CompleterBase& CompleterBase::operator=(CompleterBase&& other) noexcept {
  if (this != &other) {
    DropTransaction();
    transaction_ = other.transaction_;
    owned_ = other.owned_;
    needs_to_reply_ = other.needs_to_reply_;
    other.transaction_ = nullptr;
    other.owned_ = false;
    other.needs_to_reply_ = false;
  }
  return *this;
}

void CompleterBase::Close(zx_status_t status) {
  ScopedLock lock(lock_);
  EnsureHasTransaction(&lock);
  transaction_->Close(status);
  DropTransaction();
}

bool CompleterBase::is_reply_needed() const {
  ScopedLock lock(lock_);
  if (!needs_to_reply_)
    return false;
  if (!transaction_ || transaction_->DidOrGoingToUnbind())
    return false;
  return true;
}

void CompleterBase::EnableNextDispatch() {
  ScopedLock lock(lock_);
  EnsureHasTransaction(&lock);
  transaction_->EnableNextDispatch();
}

CompleterBase::CompleterBase(CompleterBase&& other) noexcept
    : transaction_(other.transaction_),
      reply_result_(other.reply_result_),
      owned_(other.owned_),
      needs_to_reply_(other.needs_to_reply_) {
  other.transaction_ = nullptr;
  other.reply_result_.reset();
  other.owned_ = false;
  other.needs_to_reply_ = false;
}

CompleterBase::~CompleterBase() {
  ZX_ASSERT_MSG(!is_reply_needed(), "Completer expected a Reply to be sent.");
  DropTransaction();
}

std::unique_ptr<Transaction> CompleterBase::TakeOwnership() {
  ScopedLock lock(lock_);
  EnsureHasTransaction(&lock);
  std::unique_ptr<Transaction> clone = transaction_->TakeOwnership();
  DropTransaction();
  return clone;
}

fidl::Status CompleterBase::result_of_reply() const {
  if (!reply_result_.has_value()) {
    ZX_PANIC("Did not make a reply on this completer.");
  }
  return reply_result_.value();
}

void CompleterBase::SendReply(::fidl::OutgoingMessage* message,
                              internal::OutgoingTransportContext transport_context) {
  ScopedLock lock(lock_);
  EnsureHasTransaction(&lock);
  if (unlikely(!needs_to_reply_)) {
    lock.release();  // Avoid crashing on death tests.
    ZX_PANIC("Repeated or unexpected Reply.");
  }
  // At this point we are either replying or calling InternalError, so no need for
  // further replies.
  needs_to_reply_ = false;
  if (!message->ok()) {
    transaction_->InternalError(fidl::UnbindInfo{*message}, fidl::ErrorOrigin::kSend);
    reply_result_.emplace(*message);
    return;
  }
  fidl::WriteOptions write_options = {
      .outgoing_transport_context = std::move(transport_context),
  };
  zx_status_t status = transaction_->Reply(message, std::move(write_options));
  if (status != ZX_OK) {
    auto error = fidl::Status::TransportError(status);
    transaction_->InternalError(fidl::UnbindInfo{error}, fidl::ErrorOrigin::kSend);
    reply_result_.emplace(error);
    return;
  }
  reply_result_.emplace(fidl::Status::Ok());
}

void CompleterBase::EnsureHasTransaction(ScopedLock* lock) {
  if (unlikely(!transaction_)) {
    lock->release();  // Avoid crashing on death tests.
    ZX_PANIC("ToAsync() was already called.");
  }
}

void CompleterBase::DropTransaction() {
  if (owned_) {
    owned_ = false;
    delete transaction_;
  }
  transaction_ = nullptr;
  needs_to_reply_ = false;
}

}  // namespace fidl
