// Copyright 2017 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/modular/lib/entity/cpp/json.h"

#include <string>

#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "src/lib/fxl/logging.h"

namespace modular {

constexpr char kEntityTypeProperty[] = "@type";
constexpr char kEntityRefAttribute[] = "@entityRef";

constexpr char kEntityTypeString[] = "com.google.fuchsia.string";
// We use |kEntityTypeUnknown| if the entity doesn't have a type.
constexpr char kEntityTypeUnknown[] = "com.google.fuchsia.unknown";

std::string EntityReferenceToJson(const std::string& ref) {
  auto doc = EntityReferenceToJsonDoc(ref);

  rapidjson::StringBuffer buffer;
  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  doc.Accept(writer);
  return buffer.GetString();
}

rapidjson::Document EntityReferenceToJsonDoc(const std::string& ref) {
  // Create an object that looks like:
  // {
  //   "@entityRef": "<ref string>"
  // }
  rapidjson::Document doc;
  doc.SetObject();
  rapidjson::Value str;
  str.SetString(ref, doc.GetAllocator());
  doc.AddMember(kEntityRefAttribute, str, doc.GetAllocator());
  return doc;
}

bool EntityReferenceFromJson(const std::string& json, std::string* ref) {
  rapidjson::Document doc;
  doc.Parse(json);
  if (doc.HasParseError())
    return false;
  return EntityReferenceFromJson(doc, ref);
}
bool EntityReferenceFromJson(const rapidjson::Value& value, std::string* ref) {
  if (!value.IsObject() || !value.HasMember(kEntityRefAttribute))
    return false;

  auto& attr = value[kEntityRefAttribute];
  if (!attr.IsString())
    return false;
  *ref = attr.GetString();
  return true;
}

bool ExtractEntityTypesFromJson(const std::string& json, std::vector<std::string>* const output) {
  FXL_CHECK(output != nullptr);
  // If the content has the @type attribute, take its contents and populate the
  // fuchsia::modular::EntityMetadata appropriately, overriding whatever is
  // there.
  rapidjson::Document doc;
  doc.Parse(json);
  if (doc.HasParseError()) {
    FXL_LOG(WARNING) << "Error parsing JSON: " << doc.GetParseError();
    return false;
  }

  return ExtractEntityTypesFromJson(doc, output);
}

bool ExtractEntityTypesFromJson(const rapidjson::Value& value,
                                std::vector<std::string>* const output) {
  std::vector<std::string> entity_types;

  if (value.IsString()) {
    entity_types.emplace_back(kEntityTypeString);
  } else if (value.IsObject() && value.HasMember(kEntityTypeProperty)) {
    const auto& types = value[kEntityTypeProperty];
    if (types.IsString()) {
      entity_types.emplace_back(types.GetString());
    } else if (types.IsArray()) {
      for (uint32_t i = 0; i < types.Size(); ++i) {
        if (!types[i].IsString())
          return false;
        entity_types.emplace_back(types[i].GetString());
      }
    } else {
      return false;
    }
  } else {
    entity_types.push_back(kEntityTypeUnknown);
  }

  output->swap(entity_types);
  return true;
}

}  // namespace modular
