// 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 <lib/entity/cpp/json.h>

#include <string>

#include <lib/fxl/logging.h>

#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.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
