#include "aos/json_to_flatbuffer.h"

#include <cstddef>
#include "stdio.h"

#include <string_view>

#include "aos/flatbuffer_utils.h"
#include "aos/json_tokenizer.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/minireflect.h"
#include "glog/logging.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 {

// Finds the field index in the table given the name.
int FieldIndex(const flatbuffers::TypeTable *typetable,
               const char *field_name) {
  CHECK(typetable->values == nullptr);
  for (size_t i = 0; i < typetable->num_elems; ++i) {
    if (strcmp(field_name, typetable->names[i]) == 0) {
      return i;
    }
  }
  return -1;
}

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(const flatbuffers::TypeTable *typetable,
                      const FieldElement &field_element,
                      ::std::vector<bool> *fields_in_use,
                      flatbuffers::FlatBufferBuilder *fbb);
bool AddSingleElement(const flatbuffers::TypeTable *typetable, int field_index,
                      int64_t int_value, flatbuffers::FlatBufferBuilder *fbb);
bool AddSingleElement(const flatbuffers::TypeTable *typetable, int field_index,
                      double double_value, flatbuffers::FlatBufferBuilder *fbb);
bool AddSingleElement(const flatbuffers::TypeTable *typetable, int field_index,
                      flatbuffers::Offset<flatbuffers::String> offset_element,
                      flatbuffers::FlatBufferBuilder *fbb);

// Writes an array of FieldElement (with the definition in the type
// table) to the builder.  Returns the offset of the table.
flatbuffers::uoffset_t WriteTable(const flatbuffers::TypeTable *typetable,
                                  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(typetable->num_elems, false);

  for (const FieldElement &field_element : elements) {
    AddSingleElement(typetable, 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, const flatbuffers::TypeTable *typetable) {
    flatbuffers::uoffset_t end = 0;
    bool result = DoParse(typetable, 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(const flatbuffers::TypeTable *typetable,
               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.
    const flatbuffers::TypeTable *typetable;
    // 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(const flatbuffers::TypeTable *typetable,
                         const std::string_view data,
                         flatbuffers::uoffset_t *table_end) {
  ::std::vector<const flatbuffers::TypeTable *> 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({typetable, false, -1, "", {}, {}});
        } else {
          int field_index = stack_.back().field_index;

          const flatbuffers::TypeCode &type_code =
              stack_.back().typetable->type_codes[field_index];

          if (type_code.base_type != flatbuffers::ET_SEQUENCE) {
            fprintf(stderr, "Field '%s' is not a sequence\n",
                    stack_.back().field_name.c_str());
            return false;
          }

          flatbuffers::TypeFunction type_function =
              stack_.back().typetable->type_refs[type_code.sequence_ref];

          stack_.push_back({type_function(), 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().typetable, 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 = FieldIndex(
            stack_.back().typetable, 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) {
  flatbuffers::TypeCode type_code =
      stack_.back().typetable->type_codes[field_index];

  if (type_code.is_vector != 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) {
  flatbuffers::TypeCode type_code =
      stack_.back().typetable->type_codes[field_index];

  if (type_code.is_vector != 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) {
  flatbuffers::TypeCode type_code =
      stack_.back().typetable->type_codes[field_index];

  if (type_code.is_vector != 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 =
      static_cast<flatbuffers::ElementaryType>(type_code.base_type);
  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 (type_code.sequence_ref != -1) {
        // We have an enum.
        const flatbuffers::TypeTable *type_table = stack_.back().typetable;
        flatbuffers::TypeFunction type_function =
            type_table->type_refs[type_code.sequence_ref];

        const flatbuffers::TypeTable *enum_type_table = type_function();

        CHECK_EQ(enum_type_table->st, flatbuffers::ST_ENUM);

        int64_t int_value = 0;
        bool found = false;
        for (size_t i = 0; i < enum_type_table->num_elems; ++i) {
          if (data == enum_type_table->names[i]) {
            int_value = i;
            found = true;
            break;
          }
        }

        if (!found) {
          fprintf(stderr, "Enum value '%s' not found for field '%s'\n",
                  data.c_str(), type_table->names[field_index]);
          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(const flatbuffers::TypeTable *typetable,
                      const FieldElement &field_element,
                      ::std::vector<bool> *fields_in_use,
                      flatbuffers::FlatBufferBuilder *fbb) {
  if ((*fields_in_use)[field_element.field_index]) {
    fprintf(stderr, "Duplicate field: '%s'\n",
            typetable->names[field_element.field_index]);
    return false;
  }

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

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

bool AddSingleElement(const flatbuffers::TypeTable *typetable, int field_index,
                      int64_t int_value, flatbuffers::FlatBufferBuilder *fbb

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

  flatbuffers::TypeCode type_code = typetable->type_codes[field_index];

  const flatbuffers::ElementaryType elementary_type =
      static_cast<flatbuffers::ElementaryType>(type_code.base_type);
  switch (elementary_type) {
    case flatbuffers::ET_BOOL:
      fbb->AddElement<bool>(field_offset, int_value, 0);
      return true;
    case flatbuffers::ET_CHAR:
      fbb->AddElement<int8_t>(field_offset, int_value, 0);
      return true;
    case flatbuffers::ET_UCHAR:
      fbb->AddElement<uint8_t>(field_offset, int_value, 0);
      return true;
    case flatbuffers::ET_SHORT:
      fbb->AddElement<int16_t>(field_offset, int_value, 0);
      return true;
    case flatbuffers::ET_USHORT:
      fbb->AddElement<uint16_t>(field_offset, int_value, 0);
      return true;
    case flatbuffers::ET_INT:
      fbb->AddElement<int32_t>(field_offset, int_value, 0);
      return true;
    case flatbuffers::ET_UINT:
      fbb->AddElement<uint32_t>(field_offset, int_value, 0);
      return true;
    case flatbuffers::ET_LONG:
      fbb->AddElement<int64_t>(field_offset, int_value, 0);
      return true;
    case flatbuffers::ET_ULONG:
      fbb->AddElement<uint64_t>(field_offset, int_value, 0);
      return true;
    case flatbuffers::ET_FLOAT:
      fbb->AddElement<float>(field_offset, int_value, 0);
      return true;
    case flatbuffers::ET_DOUBLE:
      fbb->AddElement<double>(field_offset, int_value, 0);
      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",
          typetable->names[field_index], ElementaryTypeName(elementary_type));
      return false;
  };
  return false;
}

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

  flatbuffers::TypeCode type_code = typetable->type_codes[field_index];

  const flatbuffers::ElementaryType elementary_type =
      static_cast<flatbuffers::ElementaryType>(type_code.base_type);
  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",
          typetable->names[field_index], ElementaryTypeName(elementary_type));
      return false;
    case flatbuffers::ET_FLOAT:
      fbb->AddElement<float>(field_offset, double_value, 0);
      return true;
    case flatbuffers::ET_DOUBLE:
      fbb->AddElement<double>(field_offset, double_value, 0);
      return true;
  }
  return false;
}
bool AddSingleElement(const flatbuffers::TypeTable *typetable, int field_index,
                      flatbuffers::Offset<flatbuffers::String> offset_element,
                      flatbuffers::FlatBufferBuilder *fbb) {
  flatbuffers::TypeCode type_code = typetable->type_codes[field_index];

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

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

  const flatbuffers::ElementaryType elementary_type =
      static_cast<flatbuffers::ElementaryType>(type_code.base_type);
  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:
      fprintf(
          stderr, "Mismatched type for field '%s'. Got: string, expected %s\n",
          typetable->names[field_index], ElementaryTypeName(elementary_type));
      CHECK_EQ(type_code.sequence_ref, -1)
          << ": Field name " << typetable->names[field_index]
          << " Got string expected " << ElementaryTypeName(elementary_type);
      return false;
    case flatbuffers::ET_STRING:
      CHECK_EQ(type_code.sequence_ref, -1);
    case flatbuffers::ET_SEQUENCE:
      fbb->AddOffset(field_offset, offset_element);
      return true;
  }
  return false;
}

bool JsonParser::FinishVector(int field_index) {
  flatbuffers::TypeCode type_code =
      stack_.back().typetable->type_codes[field_index];

  const flatbuffers::ElementaryType elementary_type =
      static_cast<flatbuffers::ElementaryType>(type_code.base_type);

  // Vectors have a start (unfortunately which needs to know the size)
  fbb_->StartVector(
      stack_.back().vector_elements.size(),
      flatbuffers::InlineSize(elementary_type, stack_.back().typetable));

  // 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:
        CHECK_EQ(type_code.sequence_ref, -1)
            << ": Field index is " << field_index;
        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, const flatbuffers::TypeTable *typetable,
    flatbuffers::FlatBufferBuilder *fbb) {
  JsonParser p(fbb);
  return p.Parse(data, typetable);
}

flatbuffers::DetachedBuffer JsonToFlatbuffer(
    const std::string_view data, const flatbuffers::TypeTable *typetable) {
  flatbuffers::FlatBufferBuilder fbb;
  fbb.ForceDefaults(true);

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

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

::std::string BufferFlatbufferToJson(const uint8_t *buffer,
                                     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 (buffer == nullptr) {
    return "null";
  }
  return TableFlatbufferToJson(reinterpret_cast<const flatbuffers::Table *>(
                                   flatbuffers::GetRoot<uint8_t>(buffer)),
                               typetable, json_options);
}

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_vector, 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_vector, 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
