// Copyright 2021 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/status.h>
#include <lib/fit/nullable.h>
#include <zircon/compiler.h>

#include <array>
#include <iostream>
#include <string>
#include <string_view>

namespace fidl {

namespace internal {

const char* const kErrorInvalidHeader = "invalid header";
const char* const kErrorUnknownTxId = "unknown txid";
const char* const kErrorUnknownOrdinal = "unknown ordinal";
const char* const kErrorTransport = "underlying transport I/O error";
const char* const kErrorChannelUnbound = "failed outgoing operation on unbound channel";
const char* const kErrorWaitOneFailed = "zx_channel_wait_one failed";
const char* const kErrorSyncEventBufferTooSmall =
    "received a larger message than allowed by the events";
const char* const kErrorSyncEventUnhandledTransitionalEvent = "unhandled transitional event";
const char* const kCallerAllocatedBufferTooSmall =
    "buffer provided to caller-allocating flavor is too small";
const char* const kUnknownInteraction = "peer did not recognize this method";
const char* const kUnsupportedTransportError =
    "server sent a transport_err value that is not supported";

}  // namespace internal

namespace {

// A buffer of 256 bytes is sufficient for all tested results.
// If the description exceeds this length at runtime,
// the output will be truncated.
// We can increase the size if necessary.
using StatusFormattingBuffer = std::array<char, 256>;

}  // namespace

[[nodiscard]] std::string Status::FormatDescription() const {
  StatusFormattingBuffer buf;
  size_t length = FormatImpl(buf.begin(), sizeof(buf), /* from_unbind_info */ false);
  return std::string(buf.begin(), length);
}

[[nodiscard]] const char* Status::lossy_description() const {
  // If an error string was explicitly specified, use that.
  if (error_) {
    return error_;
  }
  // Otherwise, derive an error from |reason_|.
  return reason_description();
}

[[nodiscard]] const char* Status::reason_description() const {
  // The error descriptions are quite terse to save binary size.
  switch (reason_) {
    case internal::kUninitializedReason:
      return nullptr;
    case Reason::kUnbind:
      return "user initiated unbind";
    case Reason::kClose:
      return "(server) user initiated close with epitaph";
    case Reason::kPeerClosed:
      return "peer closed";
    case Reason::kDispatcherError:
      return "dispatcher error";
    case Reason::kTransportError:
      return internal::kErrorTransport;
    case Reason::kEncodeError:
      return "encode error";
    case Reason::kDecodeError:
      return "decode error";
    case Reason::kUnexpectedMessage:
      return "unexpected message";
    case Reason::kUnknownInteraction:
      return "unknown interaction";
  }
}

size_t Status::FormatImpl(char* destination, size_t length, bool from_unbind_info) const {
  ZX_ASSERT(length > 0);
  int num_would_write = 0;

  // We use |snprintf| since it minimizes allocation and is faster
  // than output streams.
  if (!from_unbind_info && status_ == ZX_OK && reason_ == internal::kUninitializedReason) {
    num_would_write = snprintf(destination, length, "FIDL success");
  } else {
    const char* prelude = from_unbind_info ? "FIDL endpoint was unbound" : "FIDL operation failed";

    const char* status_meaning = [&] {
      switch (reason_) {
        // This reason may only appear in an |UnbindInfo|.
        case Reason::kClose:
          ZX_DEBUG_ASSERT(from_unbind_info);
          return "status of sending epitaph";
        case Reason::kPeerClosed:
          if (status_ != ZX_ERR_PEER_CLOSED) {
            return "epitaph";
          }
          break;
        default:
          break;
      }
      return "status";
    }();

    const char* detail_prefix = error_ ? ", detail: " : "";
    const char* detail = error_ ? error_ : "";

#ifdef __Fuchsia__
    num_would_write = snprintf(destination, length, "%s due to %s, %s: %s (%d)%s%s", prelude,
                               reason_description(), status_meaning, status_string(), status_,
                               detail_prefix, detail);
#else
    num_would_write =
        snprintf(destination, length, "%s due to %s, %s: %d%s%s", prelude, reason_description(),
                 status_meaning, status_, detail_prefix, detail);
#endif  // __Fuchsia__
  }

  ZX_ASSERT(num_would_write > 0);
  return static_cast<size_t>(num_would_write) >= length ? length - 1 : num_would_write;
}

std::ostream& operator<<(std::ostream& ostream, const Status& result) {
  StatusFormattingBuffer buf;
  size_t length = result.FormatImpl(buf.begin(), sizeof(buf), /* from_unbind_info */ false);
  ostream << std::string_view(buf.begin(), length);
  return ostream;
}

[[nodiscard]] std::string UnbindInfo::FormatDescription() const {
  StatusFormattingBuffer buf;
  size_t length = FormatImpl(buf.begin(), sizeof(buf), /* from_unbind_info */ true);
  return std::string(buf.begin(), length);
}

std::ostream& operator<<(std::ostream& ostream, const UnbindInfo& info) {
  StatusFormattingBuffer buf;
  size_t length = info.Status::FormatImpl(buf.begin(), sizeof(buf), /* from_unbind_info */ true);
  ostream << std::string_view(buf.begin(), length);
  return ostream;
}

size_t fidl::internal::DisplayError<fidl::Status>::Format(const fidl::Status& value,
                                                          char* destination, size_t capacity) {
  return value.FormatImpl(destination, capacity, false);
}

}  // namespace fidl
