// 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)
    : dispatcher_(dispatcher),
      services_(services),
      metadata_(services, clock, is_first_instance, annotation_allowlist, attachment_allowlist),
      cobalt_(cobalt),
      datastore_(datastore),
      executor_(dispatcher_) {}

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;
              if (Archive(attachments, &(bundle.value))) {
                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
