// 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 "src/developer/forensics/feedback_data/data_provider.h"

#include <fuchsia/feedback/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <lib/fit/promise.h>
#include <lib/fit/result.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/time.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <map>
#include <memory>

#include "src/developer/forensics/feedback_data/annotations/types.h"
#include "src/developer/forensics/feedback_data/annotations/utils.h"
#include "src/developer/forensics/feedback_data/attachments/screenshot_ptr.h"
#include "src/developer/forensics/feedback_data/attachments/types.h"
#include "src/developer/forensics/feedback_data/constants.h"
#include "src/developer/forensics/feedback_data/image_conversion.h"
#include "src/developer/forensics/utils/archive.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace forensics {
namespace feedback_data {
namespace {

using fuchsia::feedback::ImageEncoding;
using fuchsia::feedback::Screenshot;
using fuchsia::feedback::Snapshot;

// Timeout for a single asynchronous piece of data, e.g., syslog collection, if the client didn't
// specify one.
//
// 30s seems reasonable to collect everything.
const zx::duration kDefaultDataTimeout = zx::sec(30);

// Timeout for requesting the screenshot from Scenic.
//
// 10 seconds seems reasonable to take a screenshot.
const zx::duration kScreenshotTimeout = zx::sec(10);

}  // namespace

DataProvider::DataProvider(async_dispatcher_t* dispatcher,
                           std::shared_ptr<sys::ServiceDirectory> services,
                           timekeeper::Clock* clock, const bool is_first_instance,
                           const AnnotationKeys& annotation_allowlist,
                           const AttachmentKeys& attachment_allowlist, cobalt::Logger* cobalt,
                           Datastore* datastore, InspectDataBudget* inspect_data_budget)
    : dispatcher_(dispatcher),
      services_(services),
      metadata_(dispatcher_, clock, is_first_instance, annotation_allowlist, attachment_allowlist),
      cobalt_(cobalt),
      datastore_(datastore),
      executor_(dispatcher_),
      inspect_data_budget_(inspect_data_budget) {}

void DataProvider::GetSnapshot(fuchsia::feedback::GetSnapshotParameters params,
                               GetSnapshotCallback callback) {
  const zx::duration timeout = (params.has_collection_timeout_per_data())
                                   ? zx::duration(params.collection_timeout_per_data())
                                   : kDefaultDataTimeout;

  const uint64_t timer_id = cobalt_->StartTimer();
  auto promise =
      ::fit::join_promises(datastore_->GetAnnotations(timeout), datastore_->GetAttachments(timeout))
          .and_then([this](std::tuple<::fit::result<Annotations>, ::fit::result<Attachments>>&
                               annotations_and_attachments) {
            Snapshot snapshot;
            std::map<std::string, std::string> attachments;

            const auto& annotations_result = std::get<0>(annotations_and_attachments);
            if (annotations_result.is_ok()) {
              snapshot.set_annotations(ToFeedbackAnnotationVector(annotations_result.value()));
            } else {
              FX_LOGS(WARNING) << "Failed to retrieve any annotations";
            }

            const auto& attachments_result = std::get<1>(annotations_and_attachments);
            if (attachments_result.is_ok()) {
              for (const auto& [key, value] : attachments_result.value()) {
                if (value.HasValue()) {
                  attachments[key] = value.Value();
                }
              }
            } else {
              FX_LOGS(WARNING) << "Failed to retrieve any attachments";
            }

            // We also add the annotations as a single extra attachment.
            // This is useful for clients that surface the annotations differently in the UI
            // but still want all the annotations to be easily downloadable in one file.
            if (snapshot.has_annotations()) {
              const auto annotations_json = ToJsonString(snapshot.annotations());
              if (annotations_json.has_value()) {
                attachments[kAttachmentAnnotations] = annotations_json.value();
              }
            }

            attachments[kAttachmentMetadata] =
                metadata_.MakeMetadata(annotations_result, attachments_result,
                                       datastore_->IsMissingNonPlatformAnnotations());

            // We bundle the attachments into a single attachment.
            if (!attachments.empty()) {
              fuchsia::feedback::Attachment bundle;
              bundle.key = kSnapshotFilename;
              std::map<std::string, ArchiveFileStats> file_size_stats;
              if (Archive(attachments, &(bundle.value), &file_size_stats)) {
                inspect_data_budget_->UpdateBudget(file_size_stats);
                cobalt_->LogCount(SnapshotVersion::kCobalt, (uint64_t)bundle.value.size);
                snapshot.set_archive(std::move(bundle));
              }
            }

            return ::fit::ok(std::move(snapshot));
          })
          .then([this, callback = std::move(callback), timer_id](::fit::result<Snapshot>& result) {
            if (result.is_error()) {
              cobalt_->LogElapsedTime(cobalt::SnapshotGenerationFlow::kFailure, timer_id);
              callback(Snapshot());
            } else {
              cobalt_->LogElapsedTime(cobalt::SnapshotGenerationFlow::kSuccess, timer_id);
              callback(result.take_value());
            }
          });

  executor_.schedule_task(std::move(promise));
}

void DataProvider::GetScreenshot(ImageEncoding encoding, GetScreenshotCallback callback) {
  auto promise =
      TakeScreenshot(
          dispatcher_, services_,
          fit::Timeout(kScreenshotTimeout,
                       [this] { cobalt_->LogOccurrence(cobalt::TimedOutData::kScreenshot); }))
          .and_then([encoding](fuchsia::ui::scenic::ScreenshotData& raw_screenshot)
                        -> ::fit::result<Screenshot> {
            Screenshot screenshot;
            screenshot.dimensions_in_px.height = raw_screenshot.info.height;
            screenshot.dimensions_in_px.width = raw_screenshot.info.width;
            switch (encoding) {
              case ImageEncoding::PNG:
                if (!RawToPng(raw_screenshot.data, raw_screenshot.info.height,
                              raw_screenshot.info.width, raw_screenshot.info.stride,
                              raw_screenshot.info.pixel_format, &screenshot.image)) {
                  FX_LOGS(ERROR) << "Failed to convert raw screenshot to PNG";
                  return ::fit::error();
                }
                break;
            }
            return ::fit::ok(std::move(screenshot));
          })
          .then([callback = std::move(callback)](::fit::result<Screenshot>& result) {
            if (!result.is_ok()) {
              callback(/*screenshot=*/nullptr);
            } else {
              callback(std::make_unique<Screenshot>(result.take_value()));
            }
          });

  executor_.schedule_task(std::move(promise));
}

}  // namespace feedback_data
}  // namespace forensics
