// Copyright 2022 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 "src/developer/forensics/feedback/attachments/kernel_log.h"

#include <inttypes.h>
#include <lib/async/cpp/task.h>
#include <lib/fpromise/bridge.h>
#include <lib/fpromise/promise.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/syscalls/log.h>

#include <variant>

#include "src/developer/forensics/utils/errors.h"
#include "src/lib/fxl/strings/join_strings.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace forensics::feedback {

KernelLog::KernelLog(async_dispatcher_t* dispatcher,
                     std::shared_ptr<sys::ServiceDirectory> services,
                     std::unique_ptr<backoff::Backoff> backoff, RedactorBase* redactor)
    : dispatcher_(dispatcher),
      services_(std::move(services)),
      backoff_(std::move(backoff)),
      redactor_(redactor) {
  read_only_log_.set_error_handler([this](const zx_status_t status) {
    FX_PLOGS(WARNING, status) << "Lost connection to fuchsia.boot.ReadOnlyLog";

    for (auto& waiting : waiting_) {
      if (waiting != nullptr) {
        waiting(Error::kConnectionError);
      }
    }

    auto self = ptr_factory_.GetWeakPtr();
    async::PostDelayedTask(
        dispatcher_,
        [self] {
          if (self) {
            self->services_->Connect(self->read_only_log_.NewRequest(self->dispatcher_));
          }
        },
        backoff_->GetNext());
  });

  services_->Connect(read_only_log_.NewRequest(dispatcher_));
}

::fpromise::promise<AttachmentValue> KernelLog::Get(const zx::duration timeout) {
  if (!read_only_log_.is_bound()) {
    return ::fpromise::make_ok_promise(AttachmentValue(Error::kConnectionError));
  }

  ::fpromise::bridge<zx::debuglog, Error> bridge;

  // Construct a promise and an object that can be used to complete the promise with a value at a
  // later point in time.
  auto consume = bridge.consumer.promise_or(::fpromise::error(Error::kLogicError));
  ::fit::callback<void(std::variant<zx::debuglog, Error>)> complete =
      [completer = std::move(bridge.completer)](std::variant<zx::debuglog, Error> result) mutable {
        if (std::holds_alternative<zx::debuglog>(result)) {
          completer.complete_ok(std::move(std::get<zx::debuglog>(result)));
        } else {
          completer.complete_error(std::get<Error>(result));
        }
      };

  auto self = ptr_factory_.GetWeakPtr();
  async::PostDelayedTask(
      dispatcher_,
      [self, complete = complete.share()]() mutable {
        if (complete != nullptr) {
          complete(Error::kTimeout);
        }
      },
      timeout);

  read_only_log_->Get([complete = complete.share()](zx::debuglog debuglog) mutable {
    if (complete != nullptr) {
      complete(std::move(debuglog));
    }
  });

  return consume
      .and_then([this](zx::debuglog& debuglog) {
        waiting_.erase(std::remove(waiting_.begin(), waiting_.end(), nullptr), waiting_.end());

        std::vector<std::string> messages;

        std::array<char, ZX_LOG_RECORD_MAX + 1> buf;
        auto* record = reinterpret_cast<zx_log_record_t*>(buf.data());

        while (debuglog.read(/*options=*/0, /*buffer=*/record,
                             /*buffer_size=*/ZX_LOG_RECORD_MAX) > 0) {
          if (auto& len = record->datalen; len != 0 && record->data[len - 1] == '\n') {
            --len;
          }
          record->data[record->datalen] = 0;

          std::string data(record->data);
          data = redactor_->Redact(data);
          messages.push_back(
              fxl::StringPrintf("[%05d.%03d] %05" PRIu64 ".%05" PRIu64 "> %s\n",
                                static_cast<int>(record->timestamp / 1000000000ULL),
                                static_cast<int>((record->timestamp / 1000000ULL) % 1000ULL),
                                record->pid, record->tid, data.c_str()));
        }

        if (messages.empty()) {
          FX_LOGS(ERROR) << "Empty kernel log";
          return ::fpromise::ok(AttachmentValue(Error::kMissingValue));
        }

        return ::fpromise::ok(AttachmentValue(fxl::JoinStrings(messages)));
      })
      .or_else([](const Error& error) { return ::fpromise::ok(AttachmentValue(error)); });
}

}  // namespace forensics::feedback
