// 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.

#ifndef SRC_LIB_FIDL_CODEC_JSON_VISITOR_H_
#define SRC_LIB_FIDL_CODEC_JSON_VISITOR_H_

#include "src/lib/fidl_codec/visitor.h"
#include "src/lib/fidl_codec/wire_object.h"
#include "src/lib/fidl_codec/wire_types.h"

namespace fidl_codec {

class JsonVisitor : public Visitor {
 public:
  JsonVisitor(rapidjson::Value* result, rapidjson::Document::AllocatorType* allocator)
      : result_(result), allocator_(allocator) {}

 private:
  void VisitValue(const Value* node, const Type* for_type) override {
    std::stringstream ss;
    PrettyPrinter printer(ss, WithoutColors, false, "", 0, /*header_on_every_line=*/false);
    node->PrettyPrint(for_type, printer);
    result_->SetString(ss.str(), *allocator_);
  }

  void VisitInvalidValue(const InvalidValue* node, const Type* for_type) override {
    result_->SetString("(invalid)", *allocator_);
  }

  void VisitEmptyPayloadValue(const EmptyPayloadValue* node, const Type* for_type) override {
    result_->SetObject();
  }

  void VisitNullValue(const NullValue* node, const Type* for_type) override { result_->SetNull(); }

  void VisitStringValue(const StringValue* node, const Type* for_type) override {
    result_->SetString(node->string().data(),
                       static_cast<rapidjson::SizeType>(node->string().size()), *allocator_);
  }

  void VisitUnionValue(const UnionValue* node, const Type* for_type) override {
    result_->SetObject();
    rapidjson::Value key;
    key.SetString(node->member().name().c_str(), *allocator_);
    result_->AddMember(key, rapidjson::Value(), *allocator_);
    JsonVisitor visitor(&(*result_)[node->member().name().c_str()], allocator_);
    node->value()->Visit(&visitor, node->member().type());
  }

  void VisitStructValue(const StructValue* node, const Type* for_type) override {
    result_->SetObject();
    for (const auto& member : node->struct_definition().members()) {
      auto it = node->fields().find(member.get());
      if (it == node->fields().end())
        continue;
      rapidjson::Value key;
      key.SetString(member->name().c_str(), *allocator_);
      result_->AddMember(key, rapidjson::Value(), *allocator_);
      JsonVisitor visitor(&(*result_)[member->name().c_str()], allocator_);
      it->second->Visit(&visitor, member->type());
    }
  }

  void VisitVectorValue(const VectorValue* node, const Type* for_type) override {
    FX_DCHECK(for_type != nullptr);
    const Type* component_type = for_type->GetComponentType();
    FX_DCHECK(component_type != nullptr);
    result_->SetArray();
    for (const auto& value : node->values()) {
      rapidjson::Value element;
      JsonVisitor visitor(&element, allocator_);
      value->Visit(&visitor, component_type);
      result_->PushBack(element, *allocator_);
    }
  }

  void VisitTableValue(const TableValue* node, const Type* for_type) override {
    result_->SetObject();
    for (const auto& member : node->table_definition().members()) {
      if (member != nullptr) {
        auto it = node->members().find(member.get());
        if ((it == node->members().end()) || (it->second == nullptr) || it->second->IsNull())
          continue;
        rapidjson::Value key;
        key.SetString(member->name().c_str(), *allocator_);
        result_->AddMember(key, rapidjson::Value(), *allocator_);
        JsonVisitor visitor(&(*result_)[member->name().c_str()], allocator_);
        it->second->Visit(&visitor, member->type());
      }
    }
  }

 private:
  rapidjson::Value* result_;
  rapidjson::Document::AllocatorType* allocator_;
};

}  // namespace fidl_codec

#endif  // SRC_LIB_FIDL_CODEC_JSON_VISITOR_H_
