#include "aos/json_to_flatbuffer.h"

#include <cstddef>
#include <cstdio>
#include <string_view>

#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/minireflect.h"
#include "glog/logging.h"

#include "aos/flatbuffer_utils.h"
#include "aos/json_tokenizer.h"

// TODO(austin): Can we just do an Offset<void> ?  It doesn't matter, so maybe
// just say that.
//
// TODO(austin): I've yet to see how to create an ET_UTYPE, so I don't know what
// one is and how to test it.  So everything rejects it.

namespace aos {
namespace {

// Class to hold one of the 3 json types for an array.
struct Element {
  // The type.
  enum class ElementType { INT, DOUBLE, OFFSET };

  // Constructs an Element holding an integer.
  Element(int64_t new_int_element)
      : int_element(new_int_element), type(ElementType::INT) {}
  // Constructs an Element holding an double.
  Element(double new_double_element)
      : double_element(new_double_element), type(ElementType::DOUBLE) {}
  // Constructs an Element holding an Offset.
  Element(flatbuffers::Offset<flatbuffers::String> new_offset_element)
      : offset_element(new_offset_element), type(ElementType::OFFSET) {}

  // Union for the various datatypes.
  union {
    int64_t int_element;
    double double_element;
    flatbuffers::Offset<flatbuffers::String> offset_element;
  };

  // And an enum signaling which one is in use.
  ElementType type;
};

// Structure to represent a field element.
struct FieldElement {
  FieldElement(int new_field_index, int64_t int_element)
      : element(int_element), field_index(new_field_index) {}
  FieldElement(int new_field_index, double double_element)
      : element(double_element), field_index(new_field_index) {}
  FieldElement(int new_field_index,
               flatbuffers::Offset<flatbuffers::String> offset_element)
      : element(offset_element), field_index(new_field_index) {}

  // Data to write.
  Element element;
  // Field index.  The type table which this index is for is stored outside this
  // object.
  int field_index;
};

// Adds a single element.  This assumes that vectors have been dealt with
// already.  Returns true on success.
bool AddSingleElement(FlatbufferType type, const FieldElement &field_element,
                      ::std::vector<bool> *fields_in_use,
                      flatbuffers::FlatBufferBuilder *fbb);
bool AddSingleElement(FlatbufferType type, int field_index, int64_t int_value,
                      flatbuffers::FlatBufferBuilder *fbb);
bool AddSingleElement(FlatbufferType type, int field_index, double double_value,
                      flatbuffers::FlatBufferBuilder *fbb);
bool AddSingleElement(FlatbufferType type, int field_index,
                      flatbuffers::Offset<flatbuffers::String> offset_element,
                      flatbuffers::FlatBufferBuilder *fbb);

// Writes an array of FieldElement (with the definition in "type") to the
// builder.  Returns the offset of the resulting table.
flatbuffers::uoffset_t WriteTable(FlatbufferType type,
                                  const ::std::vector<FieldElement> &elements,
                                  flatbuffers::FlatBufferBuilder *fbb) {
  // End of a nested struct!  Add it.
  const flatbuffers::uoffset_t start = fbb->StartTable();

  ::std::vector<bool> fields_in_use(type.NumberFields(), false);

  for (const FieldElement &field_element : elements) {
    AddSingleElement(type, field_element, &fields_in_use, fbb);
  }

  return fbb->EndTable(start);
}

// Class to parse JSON into a flatbuffer.
//
// The basic strategy is that we need to do everything backwards.  So we need to
// build up what we need to do fully in memory, then do it.
//
// The driver for this is that strings need to be fully created before the
// tables that use them.  Same for sub messages.  But, we only know we have them
// all when the structure ends.  So, store each sub message in a
// FieldElement and put them in the table at the end when we finish up
// each message.  Same goes for vectors.
class JsonParser {
 public:
  JsonParser(flatbuffers::FlatBufferBuilder *fbb) : fbb_(fbb) {}
  ~JsonParser() {}

  // Parses the json into a flatbuffer.  Returns either an empty vector on
  // error, or a vector with the flatbuffer data in it.
  flatbuffers::Offset<flatbuffers::Table> Parse(const std::string_view data,
                                                FlatbufferType type) {
    flatbuffers::uoffset_t end = 0;
    bool result = DoParse(type, data, &end);

    if (result) {
      // On success, finish the table and build the vector.
      return flatbuffers::Offset<flatbuffers::Table>(end);
    } else {
      return flatbuffers::Offset<flatbuffers::Table>(0);
    }
  }

 private:
  // Setters and getters for in_vector (at the current level of the stack)
  bool in_vector() const { return stack_.back().in_vector; }
  void set_in_vector(bool in_vector) { stack_.back().in_vector = in_vector; }

  // Parses the flatbuffer.  This is a second method so we can do easier
  // cleanup at the top level.  Returns true on success.
  bool DoParse(FlatbufferType type, const std::string_view data,
               flatbuffers::uoffset_t *table_end);

  // Adds *_value for the provided field.  If we are in a vector, queues the
  // data up in vector_elements.  Returns true on success.
  bool AddElement(int field_index, int64_t int_value);
  bool AddElement(int field_index, double double_value);
  bool AddElement(int field_index, const ::std::string &data);

  // Finishes a vector for the provided field index.  Returns true on success.
  bool FinishVector(int field_index);

  // Pushes an element as part of a vector.  Returns true on success.
  bool PushElement(flatbuffers::ElementaryType elementary_type,
                   int64_t int_value);
  bool PushElement(flatbuffers::ElementaryType elementary_type,
                   double double_value);
  bool PushElement(flatbuffers::ElementaryType elementary_type,
                   flatbuffers::Offset<flatbuffers::String> offset_value);

  flatbuffers::FlatBufferBuilder *fbb_;

  // This holds the state information that is needed as you recurse into
  // nested structures.
  struct FlatBufferContext {
    // Type of the current type.
    FlatbufferType type;
    // If true, we are parsing a vector.
    bool in_vector;
    // The field index of the current field.
    int field_index;
    // Name of the current field.
    ::std::string field_name;

    // Field elements that need to be inserted.
    ::std::vector<FieldElement> elements;

    // For scalar types (not strings, and not nested tables), the vector ends
    // up being implemented as a start and end, and a block of data.  So we
    // can't just push offsets in as we go.  We either need to reproduce the
    // logic inside flatbuffers, or build up vectors of the data.  Vectors will
    // be a bit of extra stack space, but whatever.
    //
    // Strings and nested structures are vectors of offsets.
    // into the vector. Once you get to the end, you build up a vector and
    // push that into the field.
    ::std::vector<Element> vector_elements;
  };
  ::std::vector<FlatBufferContext> stack_;
};

bool JsonParser::DoParse(FlatbufferType type, const std::string_view data,
                         flatbuffers::uoffset_t *table_end) {
  ::std::vector<FlatbufferType> stack;

  Tokenizer t(data);

  // Main loop.  Run until we get an end.
  while (true) {
    Tokenizer::TokenType token = t.Next();

    switch (token) {
      case Tokenizer::TokenType::kEnd:
        if (stack_.size() != 0) {
          fprintf(stderr, "Failed to unwind stack all the way\n");
          return false;
        } else {
          return true;
        }
        break;
      case Tokenizer::TokenType::kError:
        return false;
        break;

      case Tokenizer::TokenType::kStartObject:  // {
        if (stack_.size() == 0) {
          stack_.push_back({type, false, -1, "", {}, {}});
        } else {
          int field_index = stack_.back().field_index;

          if (!stack_.back().type.FieldIsSequence(field_index)) {
            fprintf(stderr, "Field '%s' is not a sequence\n",
                    stack_.back().field_name.c_str());
            return false;
          }

          if (in_vector() != stack_.back().type.FieldIsRepeating(field_index)) {
            fprintf(stderr,
                    "Field '%s' is%s supposed to be a vector, but is a %s.\n",
                    stack_.back().field_name.c_str(), in_vector() ? " not" : "",
                    in_vector() ? "vector" : "bare object");
            return false;
          }

          stack_.push_back({stack_.back().type.FieldType(field_index),
                            false,
                            -1,
                            "",
                            {},
                            {}});
        }
        break;
      case Tokenizer::TokenType::kEndObject:  // }
        if (stack_.size() == 0) {
          // Somehow we popped more than we pushed.  Error.
          fprintf(stderr, "Empty stack\n");
          return false;
        } else {
          // End of a nested struct!  Add it.
          const flatbuffers::uoffset_t end =
              WriteTable(stack_.back().type, stack_.back().elements, fbb_);

          // We now want to talk about the parent structure.  Pop the child.
          stack_.pop_back();

          if (stack_.size() == 0) {
            // Instead of queueing it up in the stack, return it through the
            // passed in variable.
            *table_end = end;
          } else {
            // And now we can add it.
            const int field_index = stack_.back().field_index;

            // Do the right thing if we are in a vector.
            if (in_vector()) {
              stack_.back().vector_elements.emplace_back(
                  flatbuffers::Offset<flatbuffers::String>(end));
            } else {
              stack_.back().elements.emplace_back(
                  field_index, flatbuffers::Offset<flatbuffers::String>(end));
            }
          }
        }
        break;

      case Tokenizer::TokenType::kStartArray:  // [
        if (stack_.size() == 0) {
          // We don't support an array of structs at the root level.
          return false;
        }
        // Sanity check that we aren't trying to make a vector of vectors.
        if (in_vector()) {
          return false;
        }
        set_in_vector(true);

        break;
      case Tokenizer::TokenType::kEndArray: {  // ]
        if (!in_vector()) {
          return false;
        }

        const int field_index = stack_.back().field_index;

        if (!FinishVector(field_index)) return false;

        set_in_vector(false);
      } break;

      case Tokenizer::TokenType::kTrueValue:   // true
      case Tokenizer::TokenType::kFalseValue:  // false
      case Tokenizer::TokenType::kNumberValue: {
        bool is_int = true;
        double double_value;
        long long int_value;
        if (token == Tokenizer::TokenType::kTrueValue) {
          int_value = 1;
        } else if (token == Tokenizer::TokenType::kFalseValue) {
          int_value = 0;
        } else if (!t.FieldAsInt(&int_value)) {
          if (t.FieldAsDouble(&double_value)) {
            is_int = false;
          } else {
            fprintf(stderr, "Got a invalid number '%s'\n",
                    t.field_value().c_str());
            return false;
          }
        }

        const int field_index = stack_.back().field_index;

        if (is_int) {
          // No need to get too stressed about bool vs int.  Convert them all.
          int64_t val = int_value;
          if (!AddElement(field_index, val)) return false;
        } else {
          if (!AddElement(field_index, double_value)) return false;
        }
      } break;
      case Tokenizer::TokenType::kStringValue:  // string value
      {
        const int field_index = stack_.back().field_index;

        if (!AddElement(field_index, t.field_value())) return false;
      } break;
      case Tokenizer::TokenType::kField:  // field name
      {
        stack_.back().field_name = t.field_name();
        stack_.back().field_index =
            stack_.back().type.FieldIndex(stack_.back().field_name.c_str());

        if (stack_.back().field_index == -1) {
          fprintf(stderr, "Invalid field name '%s'\n",
                  stack_.back().field_name.c_str());
          return false;
        }
      } break;
    }
  }
  return false;
}

bool JsonParser::AddElement(int field_index, int64_t int_value) {
  if (stack_.back().type.FieldIsRepeating(field_index) != in_vector()) {
    fprintf(stderr, "Type and json disagree on if we are in a vector or not\n");
    return false;
  }

  if (in_vector()) {
    stack_.back().vector_elements.emplace_back(int_value);
  } else {
    stack_.back().elements.emplace_back(field_index, int_value);
  }
  return true;
}

bool JsonParser::AddElement(int field_index, double double_value) {
  if (stack_.back().type.FieldIsRepeating(field_index) != in_vector()) {
    fprintf(stderr, "Type and json disagree on if we are in a vector or not\n");
    return false;
  }

  if (in_vector()) {
    stack_.back().vector_elements.emplace_back(double_value);
  } else {
    stack_.back().elements.emplace_back(field_index, double_value);
  }
  return true;
}

bool JsonParser::AddElement(int field_index, const ::std::string &data) {
  if (stack_.back().type.FieldIsRepeating(field_index) != in_vector()) {
    fprintf(stderr, "Type and json disagree on if we are in a vector or not\n");
    return false;
  }

  const flatbuffers::ElementaryType elementary_type =
      stack_.back().type.FieldElementaryType(field_index);
  switch (elementary_type) {
    case flatbuffers::ET_CHAR:
    case flatbuffers::ET_UCHAR:
    case flatbuffers::ET_SHORT:
    case flatbuffers::ET_USHORT:
    case flatbuffers::ET_INT:
    case flatbuffers::ET_UINT:
    case flatbuffers::ET_LONG:
    case flatbuffers::ET_ULONG:
      if (stack_.back().type.FieldIsEnum(field_index)) {
        // We have an enum.
        const FlatbufferType type = stack_.back().type;
        const FlatbufferType enum_type = type.FieldType(field_index);
        CHECK(enum_type.IsEnum());

        const std::optional<int64_t> int_value = enum_type.EnumValue(data);

        if (!int_value) {
          const std::string_view name = type.FieldName(field_index);
          fprintf(stderr, "Enum value '%s' not found for field '%.*s'\n",
                  data.c_str(), static_cast<int>(name.size()), name.data());
          return false;
        }

        if (in_vector()) {
          stack_.back().vector_elements.emplace_back(*int_value);
        } else {
          stack_.back().elements.emplace_back(field_index, *int_value);
        }
        return true;
      }
    case flatbuffers::ET_UTYPE:
    case flatbuffers::ET_BOOL:
    case flatbuffers::ET_FLOAT:
    case flatbuffers::ET_DOUBLE:
    case flatbuffers::ET_STRING:
    case flatbuffers::ET_SEQUENCE:
      break;
  }

  if (in_vector()) {
    stack_.back().vector_elements.emplace_back(fbb_->CreateString(data));
  } else {
    stack_.back().elements.emplace_back(field_index, fbb_->CreateString(data));
  }
  return true;
}

bool AddSingleElement(FlatbufferType type, const FieldElement &field_element,
                      ::std::vector<bool> *fields_in_use,
                      flatbuffers::FlatBufferBuilder *fbb) {
  if ((*fields_in_use)[field_element.field_index]) {
    const std::string_view name = type.FieldName(field_element.field_index);
    fprintf(stderr, "Duplicate field: '%.*s'\n", static_cast<int>(name.size()),
            name.data());
    return false;
  }

  (*fields_in_use)[field_element.field_index] = true;

  switch (field_element.element.type) {
    case Element::ElementType::INT:
      return AddSingleElement(type, field_element.field_index,
                              field_element.element.int_element, fbb);
    case Element::ElementType::DOUBLE:
      return AddSingleElement(type, field_element.field_index,
                              field_element.element.double_element, fbb);
    case Element::ElementType::OFFSET:
      return AddSingleElement(type, field_element.field_index,
                              field_element.element.offset_element, fbb);
  }
  return false;
}

bool AddSingleElement(FlatbufferType type, int field_index, int64_t int_value,
                      flatbuffers::FlatBufferBuilder *fbb

) {
  flatbuffers::voffset_t field_offset = flatbuffers::FieldIndexToOffset(
      static_cast<flatbuffers::voffset_t>(field_index));

  const flatbuffers::ElementaryType elementary_type =
      type.FieldElementaryType(field_index);
  switch (elementary_type) {
    case flatbuffers::ET_BOOL:
      fbb->AddElement<bool>(field_offset, int_value);
      return true;
    case flatbuffers::ET_CHAR:
      fbb->AddElement<int8_t>(field_offset, int_value);
      return true;
    case flatbuffers::ET_UCHAR:
      fbb->AddElement<uint8_t>(field_offset, int_value);
      return true;
    case flatbuffers::ET_SHORT:
      fbb->AddElement<int16_t>(field_offset, int_value);
      return true;
    case flatbuffers::ET_USHORT:
      fbb->AddElement<uint16_t>(field_offset, int_value);
      return true;
    case flatbuffers::ET_INT:
      fbb->AddElement<int32_t>(field_offset, int_value);
      return true;
    case flatbuffers::ET_UINT:
      fbb->AddElement<uint32_t>(field_offset, int_value);
      return true;
    case flatbuffers::ET_LONG:
      fbb->AddElement<int64_t>(field_offset, int_value);
      return true;
    case flatbuffers::ET_ULONG:
      fbb->AddElement<uint64_t>(field_offset, int_value);
      return true;
    case flatbuffers::ET_FLOAT:
      fbb->AddElement<float>(field_offset, int_value);
      return true;
    case flatbuffers::ET_DOUBLE:
      fbb->AddElement<double>(field_offset, int_value);
      return true;
    case flatbuffers::ET_STRING:
    case flatbuffers::ET_UTYPE:
    case flatbuffers::ET_SEQUENCE: {
      const std::string_view name = type.FieldName(field_index);
      fprintf(stderr,
              "Mismatched type for field '%.*s'. Got: integer, expected %s\n",
              static_cast<int>(name.size()), name.data(),
              ElementaryTypeName(elementary_type));
      return false;
    }
  };
  return false;
}

bool AddSingleElement(FlatbufferType type, int field_index, double double_value,
                      flatbuffers::FlatBufferBuilder *fbb) {
  flatbuffers::voffset_t field_offset = flatbuffers::FieldIndexToOffset(
      static_cast<flatbuffers::voffset_t>(field_index));

  const flatbuffers::ElementaryType elementary_type =
      type.FieldElementaryType(field_index);
  switch (elementary_type) {
    case flatbuffers::ET_UTYPE:
    case flatbuffers::ET_BOOL:
    case flatbuffers::ET_CHAR:
    case flatbuffers::ET_UCHAR:
    case flatbuffers::ET_SHORT:
    case flatbuffers::ET_USHORT:
    case flatbuffers::ET_INT:
    case flatbuffers::ET_UINT:
    case flatbuffers::ET_LONG:
    case flatbuffers::ET_ULONG:
    case flatbuffers::ET_STRING:
    case flatbuffers::ET_SEQUENCE: {
      const std::string_view name = type.FieldName(field_index);
      fprintf(stderr,
              "Mismatched type for field '%.*s'. Got: double, expected %s\n",
              static_cast<int>(name.size()), name.data(),
              ElementaryTypeName(elementary_type));
      return false;
    }
    case flatbuffers::ET_FLOAT:
      fbb->AddElement<float>(field_offset, double_value);
      return true;
    case flatbuffers::ET_DOUBLE:
      fbb->AddElement<double>(field_offset, double_value);
      return true;
  }
  return false;
}
bool AddSingleElement(FlatbufferType type, int field_index,
                      flatbuffers::Offset<flatbuffers::String> offset_element,
                      flatbuffers::FlatBufferBuilder *fbb) {
  flatbuffers::voffset_t field_offset = flatbuffers::FieldIndexToOffset(
      static_cast<flatbuffers::voffset_t>(field_index));

  // Vectors will always be Offset<>'s.
  if (type.FieldIsRepeating(field_index)) {
    fbb->AddOffset(field_offset, offset_element);
    return true;
  }

  const flatbuffers::ElementaryType elementary_type =
      type.FieldElementaryType(field_index);
  switch (elementary_type) {
    case flatbuffers::ET_CHAR:
    case flatbuffers::ET_UCHAR:
    case flatbuffers::ET_SHORT:
    case flatbuffers::ET_USHORT:
    case flatbuffers::ET_INT:
    case flatbuffers::ET_UINT:
    case flatbuffers::ET_LONG:
    case flatbuffers::ET_ULONG:
    case flatbuffers::ET_UTYPE:
    case flatbuffers::ET_BOOL:
    case flatbuffers::ET_FLOAT:
    case flatbuffers::ET_DOUBLE: {
      const std::string_view name = type.FieldName(field_index);
      fprintf(stderr,
              "Mismatched type for field '%.*s'. Got: string, expected %s\n",
              static_cast<int>(name.size()), name.data(),
              ElementaryTypeName(elementary_type));
      return false;
    }
    case flatbuffers::ET_STRING:
    case flatbuffers::ET_SEQUENCE:
      fbb->AddOffset(field_offset, offset_element);
      return true;
  }
  return false;
}

bool JsonParser::FinishVector(int field_index) {
  // Vectors have a start (unfortunately which needs to know the size)
  const size_t inline_size = stack_.back().type.FieldInlineSize(field_index);
  fbb_->StartVector(stack_.back().vector_elements.size(), inline_size,
                    /*align=*/inline_size);

  const flatbuffers::ElementaryType elementary_type =
      stack_.back().type.FieldElementaryType(field_index);

  // Then the data (in reverse order for some reason...)
  for (size_t i = stack_.back().vector_elements.size(); i > 0;) {
    const Element &element = stack_.back().vector_elements[--i];
    switch (element.type) {
      case Element::ElementType::INT:
        if (!PushElement(elementary_type, element.int_element)) return false;
        break;
      case Element::ElementType::DOUBLE:
        if (!PushElement(elementary_type, element.double_element)) return false;
        break;
      case Element::ElementType::OFFSET:
        if (!PushElement(elementary_type, element.offset_element)) return false;
        break;
    }
  }

  // Then an End which is placed into the buffer the same as any other offset.
  stack_.back().elements.emplace_back(
      field_index, flatbuffers::Offset<flatbuffers::String>(
                       fbb_->EndVector(stack_.back().vector_elements.size())));
  stack_.back().vector_elements.clear();
  return true;
}

bool JsonParser::PushElement(flatbuffers::ElementaryType elementary_type,
                             int64_t int_value) {
  switch (elementary_type) {
    case flatbuffers::ET_BOOL:
      fbb_->PushElement<bool>(int_value);
      return true;
    case flatbuffers::ET_CHAR:
      fbb_->PushElement<int8_t>(int_value);
      return true;
    case flatbuffers::ET_UCHAR:
      fbb_->PushElement<uint8_t>(int_value);
      return true;
    case flatbuffers::ET_SHORT:
      fbb_->PushElement<int16_t>(int_value);
      return true;
    case flatbuffers::ET_USHORT:
      fbb_->PushElement<uint16_t>(int_value);
      return true;
    case flatbuffers::ET_INT:
      fbb_->PushElement<int32_t>(int_value);
      return true;
    case flatbuffers::ET_UINT:
      fbb_->PushElement<uint32_t>(int_value);
      return true;
    case flatbuffers::ET_LONG:
      fbb_->PushElement<int64_t>(int_value);
      return true;
    case flatbuffers::ET_ULONG:
      fbb_->PushElement<uint64_t>(int_value);
      return true;
    case flatbuffers::ET_FLOAT:
      fbb_->PushElement<float>(int_value);
      return true;
    case flatbuffers::ET_DOUBLE:
      fbb_->PushElement<double>(int_value);
      return true;
    case flatbuffers::ET_STRING:
    case flatbuffers::ET_UTYPE:
    case flatbuffers::ET_SEQUENCE:
      fprintf(stderr,
              "Mismatched type for field '%s'. Got: integer, expected %s\n",
              stack_.back().field_name.c_str(),
              ElementaryTypeName(elementary_type));
      return false;
  };
  return false;
}

bool JsonParser::PushElement(flatbuffers::ElementaryType elementary_type,
                             double double_value) {
  switch (elementary_type) {
    case flatbuffers::ET_UTYPE:
    case flatbuffers::ET_BOOL:
    case flatbuffers::ET_CHAR:
    case flatbuffers::ET_UCHAR:
    case flatbuffers::ET_SHORT:
    case flatbuffers::ET_USHORT:
    case flatbuffers::ET_INT:
    case flatbuffers::ET_UINT:
    case flatbuffers::ET_LONG:
    case flatbuffers::ET_ULONG:
    case flatbuffers::ET_STRING:
    case flatbuffers::ET_SEQUENCE:
      fprintf(stderr,
              "Mismatched type for field '%s'. Got: double, expected %s\n",
              stack_.back().field_name.c_str(),
              ElementaryTypeName(elementary_type));
      return false;
    case flatbuffers::ET_FLOAT:
      fbb_->PushElement<float>(double_value);
      return true;
    case flatbuffers::ET_DOUBLE:
      fbb_->PushElement<double>(double_value);
      return true;
  }
  return false;
}

bool JsonParser::PushElement(
    flatbuffers::ElementaryType elementary_type,
    flatbuffers::Offset<flatbuffers::String> offset_value) {
  switch (elementary_type) {
    case flatbuffers::ET_UTYPE:
    case flatbuffers::ET_BOOL:
    case flatbuffers::ET_CHAR:
    case flatbuffers::ET_UCHAR:
    case flatbuffers::ET_SHORT:
    case flatbuffers::ET_USHORT:
    case flatbuffers::ET_INT:
    case flatbuffers::ET_UINT:
    case flatbuffers::ET_LONG:
    case flatbuffers::ET_ULONG:
    case flatbuffers::ET_FLOAT:
    case flatbuffers::ET_DOUBLE:
      fprintf(stderr,
              "Mismatched type for field '%s'. Got: sequence, expected %s\n",
              stack_.back().field_name.c_str(),
              ElementaryTypeName(elementary_type));
      return false;
    case flatbuffers::ET_STRING:
    case flatbuffers::ET_SEQUENCE:
      fbb_->PushElement(offset_value);
      return true;
  }
  return false;
}

}  // namespace

flatbuffers::Offset<flatbuffers::Table> JsonToFlatbuffer(
    const std::string_view data, FlatbufferType type,
    flatbuffers::FlatBufferBuilder *fbb) {
  JsonParser p(fbb);
  return p.Parse(data, type);
}

flatbuffers::DetachedBuffer JsonToFlatbuffer(const std::string_view data,
                                             FlatbufferType type) {
  flatbuffers::FlatBufferBuilder fbb;
  fbb.ForceDefaults(true);

  const flatbuffers::Offset<flatbuffers::Table> result =
      JsonToFlatbuffer(data, type, &fbb);
  if (result.o != 0) {
    fbb.Finish(result);

    return fbb.Release();
  } else {
    // Otherwise return an empty vector.
    return flatbuffers::DetachedBuffer();
  }
}

namespace {

// A visitor which manages skipping the contents of vectors that are longer than
// a specified threshold.
class TruncatingStringVisitor : public flatbuffers::IterationVisitor {
 public:
  TruncatingStringVisitor(size_t max_vector_size, std::string delimiter,
                          bool quotes, std::string indent, bool vdelimited)
      : max_vector_size_(max_vector_size),
        to_string_(delimiter, quotes, indent, vdelimited) {}
  ~TruncatingStringVisitor() override {}

  void StartSequence() override {
    if (should_skip()) return;
    to_string_.StartSequence();
  }
  void EndSequence() override {
    if (should_skip()) return;
    to_string_.EndSequence();
  }
  void Field(size_t field_idx, size_t set_idx, flatbuffers::ElementaryType type,
             bool is_repeating, const flatbuffers::TypeTable *type_table,
             const char *name, const uint8_t *val) override {
    if (should_skip()) return;
    to_string_.Field(field_idx, set_idx, type, is_repeating, type_table, name,
                     val);
  }
  void UType(uint8_t value, const char *name) override {
    if (should_skip()) return;
    to_string_.UType(value, name);
  }
  void Bool(bool value) override {
    if (should_skip()) return;
    to_string_.Bool(value);
  }
  void Char(int8_t value, const char *name) override {
    if (should_skip()) return;
    to_string_.Char(value, name);
  }
  void UChar(uint8_t value, const char *name) override {
    if (should_skip()) return;
    to_string_.UChar(value, name);
  }
  void Short(int16_t value, const char *name) override {
    if (should_skip()) return;
    to_string_.Short(value, name);
  }
  void UShort(uint16_t value, const char *name) override {
    if (should_skip()) return;
    to_string_.UShort(value, name);
  }
  void Int(int32_t value, const char *name) override {
    if (should_skip()) return;
    to_string_.Int(value, name);
  }
  void UInt(uint32_t value, const char *name) override {
    if (should_skip()) return;
    to_string_.UInt(value, name);
  }
  void Long(int64_t value) override {
    if (should_skip()) return;
    to_string_.Long(value);
  }
  void ULong(uint64_t value) override {
    if (should_skip()) return;
    to_string_.ULong(value);
  }
  void Float(float value) override {
    if (should_skip()) return;
    to_string_.Float(value);
  }
  void Double(double value) override {
    if (should_skip()) return;
    to_string_.Double(value);
  }
  void String(const flatbuffers::String *value) override {
    if (should_skip()) return;
    to_string_.String(value);
  }
  void Unknown(const uint8_t *value) override {
    if (should_skip()) return;
    to_string_.Unknown(value);
  }
  void Element(size_t i, flatbuffers::ElementaryType type,
               const flatbuffers::TypeTable *type_table,
               const uint8_t *val) override {
    if (should_skip()) return;
    to_string_.Element(i, type, type_table, val);
  }

  virtual void StartVector(size_t size) override {
    if (should_skip()) {
      ++skip_levels_;
      return;
    }
    if (size > max_vector_size_) {
      ++skip_levels_;
      to_string_.s += "[ \"... " + std::to_string(size) + " elements ...\" ]";
      return;
    }
    to_string_.StartVector(size);
  }
  virtual void EndVector() override {
    if (should_skip()) {
      --skip_levels_;
      return;
    }
    to_string_.EndVector();
  }

  std::string &string() { return to_string_.s; }

 private:
  bool should_skip() const { return skip_levels_ > 0; }

  const size_t max_vector_size_;
  flatbuffers::ToStringVisitor to_string_;
  int skip_levels_ = 0;
};

}  // namespace

::std::string TableFlatbufferToJson(const flatbuffers::Table *t,
                                    const ::flatbuffers::TypeTable *typetable,
                                    JsonOptions json_options) {
  // It is pretty common to get passed in a nullptr when a test fails.  Rather
  // than CHECK, return a more user friendly result.
  if (t == nullptr) {
    return "null";
  }
  TruncatingStringVisitor tostring_visitor(
      json_options.max_vector_size, json_options.multi_line ? "\n" : " ", true,
      json_options.multi_line ? " " : "", json_options.multi_line);
  flatbuffers::IterateObject(reinterpret_cast<const uint8_t *>(t), typetable,
                             &tostring_visitor);
  return tostring_visitor.string();
}

}  // namespace aos
