// 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 TOOLS_FIDL_FIDLC_INCLUDE_FIDL_JSON_WRITER_H_
#define TOOLS_FIDL_FIDLC_INCLUDE_FIDL_JSON_WRITER_H_

#include <lib/fit/function.h>

#include <ostream>
#include <string_view>
#include <vector>

namespace fidl {
namespace utils {

// Methods or functions named "Emit..." are the actual protocol to
// the JSON output.

// Other public methods take various value types and generate JSON
// output via the "Emit" routines.

// |JsonWriter| requires the derived type as a template parameter so it can
// match methods declared with parameter overrides in the derived class.
template <typename DerivedT>
class JsonWriter {
 public:
  JsonWriter(std::ostream& os, int indent_level = 0) : os_(os), indent_level_(indent_level) {}

  ~JsonWriter() = default;

  template <typename Iterator>
  void GenerateArray(Iterator begin, Iterator end) {
    EmitArrayBegin();

    if (begin != end) {
      Indent();
      EmitNewlineWithIndent();
    }

    for (Iterator it = begin; it != end; ++it) {
      if (it != begin)
        EmitArraySeparator();
      self.Generate(*it);
    }

    if (begin != end) {
      Outdent();
      EmitNewlineWithIndent();
    }

    EmitArrayEnd();
  }

  template <typename Collection>
  void GenerateArray(const Collection& collection) {
    self.GenerateArray(collection.begin(), collection.end());
  }

  template <typename T>
  void Generate(const std::unique_ptr<T>& value) {
    self.Generate(*value);
  }

  template <typename T>
  void Generate(const std::vector<T>& value) {
    self.GenerateArray(value);
  }

  void Generate(bool value) { EmitBoolean(value); }

  void Generate(std::string_view value) { EmitString(value); }

  void Generate(std::string value) { EmitString(value); }

  void Generate(uint32_t value) { EmitNumeric(value); }
  void Generate(int64_t value) { EmitNumeric(value); }
  void Generate(uint64_t value) { EmitNumeric(value); }

  void ResetIndentLevel() { indent_level_ = 0; }

  void Indent() { indent_level_++; }

  void Outdent() { indent_level_--; }

  // Similar to |this| pointer, the |self| reference is simply pre-cast to the
  // derived type. Methods called with template-typed parameters (such as
  // this->Generate(obj)) would only see the Generate() methods and acceptable
  // parameter types defined within this base class, but when called using
  // self.Generate(obj), the type of obj can be matched to all Generate()
  // methods declared by both the derived type and exposed from its base
  // class (this class).
  DerivedT& self = *static_cast<DerivedT*>(this);

 protected:
  enum class Position {
    kFirst,
    kSubsequent,
  };

  // ConstantStyle indicates whether the constant value to be emitted should be
  // directly placed in the JSON output, or whether is must be wrapped in a
  // string.
  enum ConstantStyle {
    kAsConstant,
    kAsString,
  };

  void GenerateEOF() { EmitNewline(); }

  void GenerateObjectPunctuation(Position position) {
    switch (position) {
      case Position::kFirst:
        Indent();
        EmitNewlineWithIndent();
        break;
      case Position::kSubsequent:
        EmitObjectSeparator();
        break;
    }
  }

  void GenerateObject(fit::closure callback) {
    int original_indent_level = indent_level_;

    EmitObjectBegin();

    callback();

    if (indent_level_ > original_indent_level) {
      Outdent();
      EmitNewlineWithIndent();
    }

    EmitObjectEnd();
  }

  template <typename Type>
  void GenerateObjectMember(std::string_view key, const Type& value,
                            Position position = Position::kSubsequent) {
    GenerateObjectPunctuation(position);
    EmitObjectKey(key);
    self.Generate(value);
  }

  void EmitBoolean(bool value, ConstantStyle style = kAsConstant) {
    if (style == kAsString)
      os_ << "\"";
    if (value)
      os_ << "true";
    else
      os_ << "false";
    if (style == kAsString)
      os_ << "\"";
  }

  void EmitString(std::string_view value) {
    os_ << "\"";

    for (size_t i = 0; i < value.size(); ++i) {
      const char c = value[i];
      switch (c) {
        case '"':
          os_ << "\\\"";
          break;
        case '\\':
          os_ << "\\\\";
          break;
        case '\n':
          os_ << "\\n";
          break;
        // TODO(fxbug.dev/7365): Escape more characters.
        default:
          os_ << c;
          break;
      }
    }
    os_ << "\"";
  }

  void EmitLiteral(std::string_view value) { os_.rdbuf()->sputn(value.data(), value.size()); }

  template <typename ValueType>
  void EmitNumeric(ValueType value, ConstantStyle style = kAsConstant) {
    static_assert(std::is_arithmetic<ValueType>::value && !std::is_same<ValueType, bool>::value,
                  "EmitNumeric can only be used with a numeric ValueType!");
    static_assert(std::is_arithmetic<ValueType>::value && !std::is_same<ValueType, uint8_t>::value,
                  "EmitNumeric does not work for uint8_t, upcast to uint64_t");
    static_assert(std::is_arithmetic<ValueType>::value && !std::is_same<ValueType, int8_t>::value,
                  "EmitNumeric does not work for int8_t, upcast to int64_t");

    switch (style) {
      case ConstantStyle::kAsConstant:
        os_ << value;
        break;
      case ConstantStyle::kAsString:
        os_ << "\"" << value << "\"";
        break;
    }
  }

  void EmitNewline() { os_ << "\n"; }

  void EmitNewlineWithIndent() {
    os_ << "\n";
    int indent_level = indent_level_;
    while (indent_level--)
      os_ << kIndent;
  }

  void EmitObjectBegin() { os_ << "{"; }

  void EmitObjectSeparator() {
    os_ << ",";
    EmitNewlineWithIndent();
  }

  void EmitObjectEnd() { os_ << "}"; }

  void EmitObjectKey(std::string_view key) {
    EmitString(key);
    os_ << ": ";
  }

  void EmitArrayBegin() { os_ << "["; }

  void EmitArraySeparator() {
    os_ << ",";
    EmitNewlineWithIndent();
  }

  void EmitArrayEnd() { os_ << "]"; }

 private:
  static constexpr const char* kIndent = "  ";
  std::ostream& os_;
  int indent_level_;
};

}  // namespace utils
}  // namespace fidl

#endif  // TOOLS_FIDL_FIDLC_INCLUDE_FIDL_JSON_WRITER_H_
