#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, STRUCT };

  // Constructs an Element holding an integer.
  Element(absl::int128 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) {}
  // Constructs an Element holding a struct.
  Element(std::vector<uint8_t> struct_data)
      : /*initialize the union member to keep the compiler happy*/ int_element(
            0),
        struct_data(std::move(struct_data)),
        type(ElementType::STRUCT) {}

  // Union for the various datatypes.
  union {
    absl::int128 int_element;
    double double_element;
    flatbuffers::Offset<flatbuffers::String> offset_element;
  };
  // Because we can't know the maximum size of any potential structs at
  // compile-time, we will use a vector to store the vector data inline.
  // If you were to do a reinterpret_cast<StructType*>(struct_data.data()) then
  // you would have an instance of the struct in question.
  std::vector<uint8_t> struct_data;

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

// Structure to represent a field element.
struct FieldElement {
  FieldElement(int new_field_index, absl::int128 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) {}
  FieldElement(int new_field_index, const Element &element)
      : element(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,
                      absl::int128 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);
bool AddSingleElement(FlatbufferType type, int field_index,
                      const std::vector<uint8_t> &struct_data,
                      flatbuffers::FlatBufferBuilder *fbb);

template <typename T, typename U>
void SetMemory(U value, uint8_t *destination) {
  // destination may be poorly aligned. As such, we should not simply do
  // *reinterpret_cast<T*>(destination) = value directly.
  const T casted = static_cast<T>(value);
  memcpy(destination, &casted, sizeof(T));
}

bool SetStructElement(FlatbufferType type, int field_index, absl::int128 value,
                      uint8_t *destination) {
  const flatbuffers::ElementaryType elementary_type =
      type.FieldElementaryType(field_index);
  switch (elementary_type) {
    case flatbuffers::ET_CHAR:
      SetMemory<int8_t>(value, destination);
      break;
    case flatbuffers::ET_UCHAR:
      SetMemory<uint8_t>(value, destination);
      break;
    case flatbuffers::ET_SHORT:
      SetMemory<int16_t>(value, destination);
      break;
    case flatbuffers::ET_USHORT:
      SetMemory<uint16_t>(value, destination);
      break;
    case flatbuffers::ET_INT:
      SetMemory<int32_t>(value, destination);
      break;
    case flatbuffers::ET_UINT:
      SetMemory<uint32_t>(value, destination);
      break;
    case flatbuffers::ET_LONG:
      SetMemory<int64_t>(value, destination);
      break;
    case flatbuffers::ET_ULONG:
      SetMemory<uint64_t>(value, destination);
      break;
    case flatbuffers::ET_BOOL:
      SetMemory<bool>(value, destination);
      break;
    case flatbuffers::ET_FLOAT:
      SetMemory<float>(value, destination);
      break;
    case flatbuffers::ET_DOUBLE:
      SetMemory<double>(value, destination);
      break;
    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 true;
}

bool SetStructElement(FlatbufferType type, int field_index, double value,
                      uint8_t *destination) {
  const flatbuffers::ElementaryType elementary_type =
      type.FieldElementaryType(field_index);
  switch (elementary_type) {
    case flatbuffers::ET_FLOAT:
      SetMemory<float>(value, destination);
      break;
    case flatbuffers::ET_DOUBLE:
      SetMemory<double>(value, destination);
      break;
    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_BOOL:
    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 true;
}

// Writes an array of FieldElement (with the definition in "type") to the
// builder.  Returns the offset of the resulting table.
std::optional<Element> WriteObject(FlatbufferType type,
                                   const ::std::vector<FieldElement> &elements,
                                   flatbuffers::FlatBufferBuilder *fbb) {
  // End of a nested object!  Add it.
  if (type.IsTable()) {
    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 Element{
        flatbuffers::Offset<flatbuffers::String>{fbb->EndTable(start)}};
  } else if (type.IsStruct()) {
    // In order to write an inline struct, we need to fill out each field at the
    // correct position inline in memory. In order to do this, we retrieve the
    // offset/size of each field, and directly populate that memory with the
    // relevant value.
    std::vector<uint8_t> buffer(type.InlineSize(), 0);
    for (size_t field_index = 0;
         field_index < static_cast<size_t>(type.NumberFields());
         ++field_index) {
      auto it = std::find_if(elements.begin(), elements.end(),
                             [field_index](const FieldElement &field) {
                               return field.field_index ==
                                      static_cast<int>(field_index);
                             });
      if (it == elements.end()) {
        fprintf(stderr,
                "All fields must be specified for struct types (field %s "
                "missing).\n",
                type.FieldName(field_index).data());
        return std::nullopt;
      }

      uint8_t *field_data = buffer.data() + type.StructFieldOffset(field_index);
      const size_t field_size = type.FieldInlineSize(field_index);
      switch (it->element.type) {
        case Element::ElementType::INT:
          if (!SetStructElement(type, field_index, it->element.int_element,
                                field_data)) {
            return std::nullopt;
          }
          break;
        case Element::ElementType::DOUBLE:
          if (!SetStructElement(type, field_index, it->element.double_element,
                                field_data)) {
            return std::nullopt;
          }
          break;
        case Element::ElementType::STRUCT:
          CHECK_EQ(field_size, it->element.struct_data.size());
          memcpy(field_data, it->element.struct_data.data(), field_size);
          break;
        case Element::ElementType::OFFSET:
          LOG(FATAL)
              << "This should be unreachable; structs cannot contain offsets.";
          break;
      }
    }
    return Element{buffer};
  }
  LOG(FATAL) << "Unimplemented.";
}

// 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, absl::int128 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,
                   absl::int128 int_value);
  bool PushElement(flatbuffers::ElementaryType elementary_type,
                   double double_value);
  bool PushElement(flatbuffers::ElementaryType elementary_type,
                   flatbuffers::Offset<flatbuffers::String> offset_value);
  bool PushElement(const FlatbufferType &type,
                   const std::vector<uint8_t> &struct_data);
  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:
        fprintf(stderr, "Encountered an error in the tokenizer\n");
        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 object!  Add it.
          std::optional<Element> object =
              WriteObject(stack_.back().type, stack_.back().elements, fbb_);
          if (!object.has_value()) {
            return false;
          }

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

          if (stack_.size() == 0) {
            CHECK_EQ(static_cast<int>(object->type),
                     static_cast<int>(Element::ElementType::OFFSET))
                << ": JSON parsing only supports parsing flatbuffer tables.";
            // Instead of queueing it up in the stack, return it through the
            // passed in variable.
            *table_end = object->offset_element.o;
          } 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(
                  std::move(object.value()));
            } else {
              stack_.back().elements.emplace_back(field_index,
                                                  std::move(object.value()));
            }
          }
        }
        break;

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

        break;
      case Tokenizer::TokenType::kEndArray: {  // ]
        if (!in_vector()) {
          fprintf(stderr, "Encountered ']' with no prior '['.\n");
          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;
        absl::int128 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.
          absl::int128 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, absl::int128 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 (JSON "
            "believes that we are%s in a vector for field '%s').\n",
            in_vector() ? "" : " not",
            stack_.back().type.FieldName(field_index).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;
}

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 (JSON "
            "believes that we are%s in a vector for field '%s').\n",
            in_vector() ? "" : " not",
            stack_.back().type.FieldName(field_index).data());
    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 (JSON "
            "believes that we are%s in a vector for field '%s').\n",
            in_vector() ? "" : " not",
            stack_.back().type.FieldName(field_index).data());
    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<absl::int128> 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);
    case Element::ElementType::STRUCT:
      return AddSingleElement(type, field_element.field_index,
                              field_element.element.struct_data, fbb);
  }
  return false;
}

bool AddSingleElement(FlatbufferType type, int field_index,
                      absl::int128 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, static_cast<bool>(int_value));
      return true;
    case flatbuffers::ET_CHAR:
      fbb->AddElement<int8_t>(field_offset, static_cast<int8_t>(int_value));
      return true;
    case flatbuffers::ET_UCHAR:
      fbb->AddElement<uint8_t>(field_offset, static_cast<uint8_t>(int_value));
      return true;
    case flatbuffers::ET_SHORT:
      fbb->AddElement<int16_t>(field_offset, static_cast<int16_t>(int_value));
      return true;
    case flatbuffers::ET_USHORT:
      fbb->AddElement<uint16_t>(field_offset, static_cast<uint16_t>(int_value));
      return true;
    case flatbuffers::ET_INT:
      fbb->AddElement<int32_t>(field_offset, static_cast<int32_t>(int_value));
      return true;
    case flatbuffers::ET_UINT:
      fbb->AddElement<uint32_t>(field_offset, static_cast<uint32_t>(int_value));
      return true;
    case flatbuffers::ET_LONG:
      fbb->AddElement<int64_t>(field_offset, static_cast<int64_t>(int_value));
      return true;
    case flatbuffers::ET_ULONG:
      fbb->AddElement<uint64_t>(field_offset, static_cast<uint64_t>(int_value));
      return true;
      // The floating point cases occur when someone specifies an integer in the
      // JSON for a double field.
    case flatbuffers::ET_FLOAT:
      fbb->AddElement<float>(field_offset, static_cast<float>(int_value));
      return true;
    case flatbuffers::ET_DOUBLE:
      fbb->AddElement<double>(field_offset, static_cast<double>(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 AddSingleElement(FlatbufferType type, int field_index,
                      const std::vector<uint8_t> &data,
                      flatbuffers::FlatBufferBuilder *fbb) {
  // Structs are always inline.
  // We have to do somewhat manual serialization to get the struct into place,
  // since the regular FlatBufferBuilder assumes that you will know the type of
  // the struct that you are constructing at compile time.
  fbb->Align(type.FieldType(field_index).Alignment());
  fbb->PushBytes(data.data(), data.size());
  fbb->AddStructOffset(flatbuffers::FieldIndexToOffset(
                           static_cast<flatbuffers::voffset_t>(field_index)),
                       fbb->GetSize());
  return true;
}

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);
  const size_t alignment = stack_.back().type.FieldInlineAlignment(field_index);
  fbb_->StartVector(stack_.back().vector_elements.size(), inline_size,
                    /*align=*/alignment);

  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;
      case Element::ElementType::STRUCT:
        if (!PushElement(stack_.back().type.FieldType(field_index),
                         element.struct_data))
          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,
                             absl::int128 int_value) {
  switch (elementary_type) {
    case flatbuffers::ET_BOOL:
      fbb_->PushElement<bool>(static_cast<bool>(int_value));
      return true;
    case flatbuffers::ET_CHAR:
      fbb_->PushElement<int8_t>(static_cast<int8_t>(int_value));
      return true;
    case flatbuffers::ET_UCHAR:
      fbb_->PushElement<uint8_t>(static_cast<uint8_t>(int_value));
      return true;
    case flatbuffers::ET_SHORT:
      fbb_->PushElement<int16_t>(static_cast<int16_t>(int_value));
      return true;
    case flatbuffers::ET_USHORT:
      fbb_->PushElement<uint16_t>(static_cast<uint16_t>(int_value));
      return true;
    case flatbuffers::ET_INT:
      fbb_->PushElement<int32_t>(static_cast<int32_t>(int_value));
      return true;
    case flatbuffers::ET_UINT:
      fbb_->PushElement<uint32_t>(static_cast<uint32_t>(int_value));
      return true;
    case flatbuffers::ET_LONG:
      fbb_->PushElement<int64_t>(static_cast<int64_t>(int_value));
      return true;
    case flatbuffers::ET_ULONG:
      fbb_->PushElement<uint64_t>(static_cast<uint64_t>(int_value));
      return true;
    case flatbuffers::ET_FLOAT:
      fbb_->PushElement<float>(static_cast<float>(int_value));
      return true;
    case flatbuffers::ET_DOUBLE:
      fbb_->PushElement<double>(static_cast<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(const FlatbufferType &type,
                             const std::vector<uint8_t> &struct_data) {
  // To add a struct to a vector, we just need to get the relevant bytes pushed
  // straight into the builder. The FlatBufferBuilder normally expects that you
  // will know the type of your struct at compile-time, so doesn't have a
  // first-class way to do this.
  fbb_->Align(type.Alignment());
  fbb_->PushBytes(struct_data.data(), struct_data.size());
  return true;
}

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
