// Copyright 2020 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/metadata.h"

#include <lib/zx/clock.h>
#include <lib/zx/time.h>
#include <zircon/utc.h>

#include <optional>
#include <set>

#include "src/developer/forensics/feedback_data/constants.h"
#include "src/developer/forensics/feedback_data/errors.h"
#include "src/developer/forensics/utils/cobalt/metrics.h"
#include "src/developer/forensics/utils/errors.h"

// TODO(fxbug.dev/57392): Move it back to //third_party once unification completes.
#include "zircon/third_party/rapidjson/include/rapidjson/document.h"
#include "zircon/third_party/rapidjson/include/rapidjson/prettywriter.h"
#include "zircon/third_party/rapidjson/include/rapidjson/rapidjson.h"
#include "zircon/third_party/rapidjson/include/rapidjson/stringbuffer.h"

namespace forensics {
namespace feedback_data {
namespace {

using namespace rapidjson;

std::set<std::string> kUtcMonotonicDifferenceAllowlist = {
    kAttachmentInspect,
    kAttachmentLogKernel,
    kAttachmentLogSystem,
};

std::set<std::string> kPreviousBootUtcMonotonicDifferenceAllowlist = {
    kAttachmentLogSystemPrevious,
};

std::string ToString(const enum AttachmentValue::State state) {
  switch (state) {
    case AttachmentValue::State::kComplete:
      return "complete";
    case AttachmentValue::State::kPartial:
      return "partial";
    case AttachmentValue::State::kMissing:
      return "missing";
  }
}

// Create a complete list set of annotations from the collected annotations and the allowlist.
Annotations AllAnnotations(const AnnotationKeys& allowlist,
                           const ::fit::result<Annotations>& annotations_result) {
  Annotations all_annotations;
  if (annotations_result.is_ok()) {
    all_annotations.insert(annotations_result.value().cbegin(), annotations_result.value().cend());
  }

  for (const auto& key : allowlist) {
    if (all_annotations.find(key) == all_annotations.end()) {
      // There is an annotation in the allowlist that was not produced by any provider. This
      // indicates a logical error on the Feedback-side.
      all_annotations.insert({key, AnnotationOr(Error::kLogicError)});
    }
  }

  return all_annotations;
}

// Create a complete list set of attachments from the collected attachments and the allowlist.
Attachments AllAttachments(const AttachmentKeys& allowlist,
                           const ::fit::result<Attachments>& attachments_result) {
  Attachments all_attachments;
  if (attachments_result.is_ok()) {
    // Because attachments can contain large blobs of text and we only care about the state of the
    // attachment and its associated error, we don't copy the value of the attachment.
    for (const auto& [k, v] : attachments_result.value()) {
      switch (v.State()) {
        case AttachmentValue::State::kComplete:
          all_attachments.insert({k, AttachmentValue("")});
          break;
        case AttachmentValue::State::kPartial:
          all_attachments.insert({k, AttachmentValue("", v.Error())});
          break;
        case AttachmentValue::State::kMissing:
          all_attachments.insert({k, v});
          break;
      }
    }
  }

  for (const auto& key : allowlist) {
    if (all_attachments.find(key) == all_attachments.end()) {
      all_attachments.insert({key, AttachmentValue(Error::kLogicError)});
    }
  }

  return all_attachments;
}

void AddUtcMonotonicDifference(const std::optional<zx::duration>& utc_monotonic_difference,
                               Value* file, Document::AllocatorType& allocator) {
  if (!utc_monotonic_difference.has_value() || !file->IsObject() ||
      file->HasMember("utc_monotonic_difference_nanos")) {
    return;
  }

  file->AddMember("utc_monotonic_difference_nanos",
                  Value().SetInt64(utc_monotonic_difference.value().get()), allocator);
}

void AddUtcMonotonicDifferences(
    const std::optional<zx::duration> utc_monotonic_difference,
    const std::optional<zx::duration> previous_boot_utc_monotonic_difference,
    Document* metadata_json) {
  if (!metadata_json->HasMember("files")) {
    return;
  }

  for (auto& file : (*metadata_json)["files"].GetObject()) {
    if (kUtcMonotonicDifferenceAllowlist.find(file.name.GetString()) !=
        kUtcMonotonicDifferenceAllowlist.end()) {
      AddUtcMonotonicDifference(utc_monotonic_difference, &file.value,
                                metadata_json->GetAllocator());
    }

    if (kPreviousBootUtcMonotonicDifferenceAllowlist.find(file.name.GetString()) !=
        kPreviousBootUtcMonotonicDifferenceAllowlist.end()) {
      AddUtcMonotonicDifference(previous_boot_utc_monotonic_difference, &file.value,
                                metadata_json->GetAllocator());
    }
  }
}

void AddAttachments(const AttachmentKeys& attachment_allowlist,
                    const ::fit::result<Attachments>& attachments_result, Document* metadata_json) {
  if (attachment_allowlist.empty()) {
    return;
  }

  auto& allocator = metadata_json->GetAllocator();
  auto MakeValue = [&allocator](const std::string& v) { return Value(v, allocator); };

  for (const auto& [name, v] : AllAttachments(attachment_allowlist, attachments_result)) {
    Value file(kObjectType);

    file.AddMember("state", MakeValue(ToString(v.State())), allocator);
    if (v.HasError()) {
      file.AddMember("error", MakeValue(ToReason(v.Error())), allocator);
    }

    (*metadata_json)["files"].AddMember(MakeValue(name), file, allocator);
  }
}

void AddAnnotationsJson(const AnnotationKeys& annotation_allowlist,
                        const ::fit::result<Annotations>& annotations_result,
                        const bool missing_non_platform_annotations, Document* metadata_json) {
  const Annotations all_annotations = AllAnnotations(annotation_allowlist, annotations_result);

  bool has_non_platform = all_annotations.size() > annotation_allowlist.size();
  if (annotation_allowlist.empty() && !(has_non_platform || missing_non_platform_annotations)) {
    return;
  }

  auto& allocator = metadata_json->GetAllocator();
  auto MakeValue = [&allocator](const std::string& v) { return Value(v, allocator); };

  Value present(kArrayType);
  Value missing(kObjectType);

  size_t num_present_platform = 0u;
  size_t num_missing_platform = 0u;
  for (const auto& [k, v] : all_annotations) {
    if (annotation_allowlist.find(k) == annotation_allowlist.end()) {
      continue;
    }

    Value key(MakeValue(k));
    if (v.HasValue()) {
      present.PushBack(key, allocator);
      ++num_present_platform;
    } else {
      missing.AddMember(key, MakeValue(ToReason(v.Error())), allocator);
      ++num_missing_platform;
    }
  }

  if (has_non_platform || missing_non_platform_annotations) {
    if (!missing_non_platform_annotations) {
      present.PushBack("non-platform annotations", allocator);
    } else {
      missing.AddMember("non-platform annotations", "too many non-platfrom annotations added",
                        allocator);
    }
  }

  Value state;
  if (num_present_platform == annotation_allowlist.size() && !missing_non_platform_annotations) {
    state = "complete";
  } else if (num_missing_platform == annotation_allowlist.size() && !has_non_platform &&
             missing_non_platform_annotations) {
    state = "missing";
  } else {
    state = "partial";
  }

  Value annotations_json(kObjectType);
  annotations_json.AddMember("state", state, allocator);
  annotations_json.AddMember("missing annotations", missing, allocator);
  annotations_json.AddMember("present annotations", present, allocator);

  (*metadata_json)["files"].AddMember("annotations.json", annotations_json, allocator);
}

}  // namespace

Metadata::Metadata(async_dispatcher_t* dispatcher, timekeeper::Clock* clock,
                   const bool is_first_instance, const AnnotationKeys& annotation_allowlist,
                   const AttachmentKeys& attachment_allowlist)
    : annotation_allowlist_(annotation_allowlist),
      attachment_allowlist_(attachment_allowlist),
      utc_provider_(dispatcher, zx::unowned_clock(zx_utc_reference_get()), clock,
                    PreviousBootFile::FromCache(is_first_instance, kUtcMonotonicDifferenceFile)) {}

std::string Metadata::MakeMetadata(const ::fit::result<Annotations>& annotations_result,
                                   const ::fit::result<Attachments>& attachments_result,
                                   bool missing_non_platform_annotations) {
  Document metadata_json(kObjectType);
  auto& allocator = metadata_json.GetAllocator();

  auto MetadataString = [&metadata_json]() {
    StringBuffer buffer;
    PrettyWriter<StringBuffer> writer(buffer);

    metadata_json.Accept(writer);

    return std::string(buffer.GetString());
  };

  // Insert all top-level fields
  metadata_json.AddMember("snapshot_version", Value(SnapshotVersion::kString, allocator),
                          allocator);
  metadata_json.AddMember("metadata_version", Value(Metadata::kVersion, allocator), allocator);
  metadata_json.AddMember("files", Value(kObjectType), allocator);

  const bool has_non_platform_annotations =
      annotations_result.is_ok() &&
      annotations_result.value().size() > annotation_allowlist_.size();

  if (annotation_allowlist_.empty() && attachment_allowlist_.empty() &&
      !has_non_platform_annotations && !missing_non_platform_annotations) {
    return MetadataString();
  }

  AddAttachments(attachment_allowlist_, attachments_result, &metadata_json);
  AddAnnotationsJson(annotation_allowlist_, annotations_result, missing_non_platform_annotations,
                     &metadata_json);
  AddUtcMonotonicDifferences(utc_provider_.CurrentUtcMonotonicDifference(),
                             utc_provider_.PreviousBootUtcMonotonicDifference(), &metadata_json);

  return MetadataString();
}

}  // namespace feedback_data
}  // namespace forensics
