// 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/inspect.h"

#include <fuchsia/diagnostics/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/fit/defer.h>
#include <lib/fit/function.h>
#include <lib/fpromise/bridge.h>
#include <lib/fpromise/promise.h>
#include <lib/fpromise/result.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/time.h>

#include <memory>
#include <string>
#include <vector>

#include "src/developer/forensics/feedback_data/constants.h"
#include "src/developer/forensics/utils/errors.h"
#include "src/lib/fsl/vmo/strings.h"
#include "src/lib/fxl/strings/join_strings.h"

namespace forensics::feedback {

Inspect::Inspect(async_dispatcher_t* dispatcher, std::shared_ptr<sys::ServiceDirectory> services,
                 std::unique_ptr<backoff::Backoff> backoff,
                 feedback_data::InspectDataBudget* data_budget)
    : dispatcher_(dispatcher),
      services_(std::move(services)),
      backoff_(std::move(backoff)),
      data_budget_(data_budget) {
  archive_accessor_.set_error_handler([this](const zx_status_t status) {
    FX_LOGS(WARNING) << "Lost connection to " << feedback_data::kArchiveAccessorName;
    auto self = ptr_factory_.GetWeakPtr();
    async::PostDelayedTask(
        dispatcher_,
        [self] {
          if (self) {
            self->services_->Connect(self->archive_accessor_.NewRequest(self->dispatcher_),
                                     feedback_data::kArchiveAccessorName);
          }
        },
        backoff_->GetNext());
  });

  services_->Connect(archive_accessor_.NewRequest(dispatcher_),
                     feedback_data::kArchiveAccessorName);
}

namespace {

// Manages collecting Inspect data and calling |complete| with done.
class InspectCollector {
 public:
  InspectCollector(::fit::callback<void(std::optional<Error>)> complete);

  void Run();

  ::fidl::InterfaceRequest<fuchsia::diagnostics::BatchIterator> NewRequest(
      async_dispatcher_t* dispatcher);
  const std::vector<std::string>& Inspect() const;

 private:
  ::fit::callback<void(std::optional<Error>)> complete_;
  fuchsia::diagnostics::BatchIteratorPtr batch_iterator_;
  std::vector<std::string> inspect_;
};

InspectCollector::InspectCollector(::fit::callback<void(std::optional<Error>)> complete)
    : complete_(std::move(complete)) {
  batch_iterator_.set_error_handler([this](const zx_status_t status) mutable {
    if (complete_ != nullptr) {
      FX_PLOGS(WARNING, status) << "Lost connection to fuchsia.diagnostics.BatchIterator";
      complete_(Error::kConnectionError);
    }
  });
}

::fidl::InterfaceRequest<fuchsia::diagnostics::BatchIterator> InspectCollector::NewRequest(
    async_dispatcher_t* dispatcher) {
  return batch_iterator_.NewRequest(dispatcher);
}

const std::vector<std::string>& InspectCollector::Inspect() const { return inspect_; }

void InspectCollector::Run() {
  if (complete_ == nullptr) {
    return;
  }

  FX_CHECK(batch_iterator_.is_bound())
      << "Attempting to collect Inspect without BatchIterator connection";

  batch_iterator_->GetNext([this](auto result) mutable {
    // Inspect collection has completed elsewhere, stop.
    if (complete_ == nullptr) {
      return;
    }

    // Get the next batch of Inspect data when done.
    auto get_next = ::fit::defer([this] { Run(); });

    // Try again if the result was an error.
    if (result.is_err()) {
      FX_LOGS(WARNING) << "Failed to retrieve Inspect batch: "
                       << static_cast<uint64_t>(result.err());
      return;
    }

    const auto& batch = result.response().batch;

    // All of the Inspect data has been collected.
    if (batch.empty()) {
      complete_(std::nullopt);
      get_next.cancel();
      return;
    }

    for (const auto& chunk : batch) {
      if (!chunk.is_json()) {
        FX_LOGS(WARNING) << "Invalid JSON Inspect chunk, skipping";
        continue;
      }

      if (std::string json; fsl::StringFromVmo(chunk.json(), &json)) {
        inspect_.push_back(std::move(json));
      } else {
        FX_LOGS(WARNING) << "Failed to convert Inspect chunk to string, skipping";
      }
    }
  });
}

}  // namespace

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

  ::fpromise::bridge<void, 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::optional<Error>)> complete =
      [completer = std::move(bridge.completer)](std::optional<Error> error) mutable {
        if (error.has_value()) {
          completer.complete_error(*error);
        } else {
          completer.complete_ok();
        }
      };

  auto collector = std::make_unique<InspectCollector>(complete.share());

  fuchsia::diagnostics::StreamParameters params;
  params.set_data_type(fuchsia::diagnostics::DataType::INSPECT)
      .set_format(fuchsia::diagnostics::Format::JSON)
      .set_stream_mode(fuchsia::diagnostics::StreamMode::SNAPSHOT)
      .set_client_selector_configuration(
          fuchsia::diagnostics::ClientSelectorConfiguration::WithSelectAll(true));

  if (const auto budget = data_budget_->SizeInBytes(); budget.has_value()) {
    fuchsia::diagnostics::PerformanceConfiguration performance;
    performance.set_max_aggregate_content_size_bytes(*budget);
    params.set_performance_configuration(std::move(performance));
  }

  archive_accessor_->StreamDiagnostics(std::move(params), collector->NewRequest(dispatcher_));

  collector->Run();
  async::PostDelayedTask(
      dispatcher_,
      [complete = complete.share()]() mutable {
        if (complete != nullptr) {
          complete(Error::kTimeout);
        }
      },
      timeout);

  // Keep |collector| alive until Inspect collection has completed (for any reason).
  return consume.then([collector = std::move(collector), complete = std::move(complete)](
                          const ::fpromise::result<void, Error>& result) mutable
                      -> ::fpromise::result<AttachmentValue> {
    auto& inspect = collector->Inspect();
    if (inspect.empty()) {
      FX_LOGS(WARNING) << "Inspect data was empty";
      return ::fpromise::ok(result.is_ok() ? Error::kMissingValue : result.error());
    }

    std::string joined_data = "[\n";
    joined_data += fxl::JoinStrings(inspect, ",\n");
    joined_data += "\n]";

    AttachmentValue value = (result.is_ok())
                                ? AttachmentValue(std::move(joined_data))
                                : AttachmentValue(std::move(joined_data), result.error());

    return ::fpromise::ok(std::move(value));
  });
}

}  // namespace forensics::feedback
