#include "test_builder.h"

#include "flatbuffers/flatbuffer_builder.h"
#include "flatbuffers/stl_emulation.h"
#include "monster_test_generated.h"

using namespace MyGame::Example;
using namespace flatbuffers;

struct OwnedAllocator : public DefaultAllocator {};

class TestHeapBuilder : public FlatBufferBuilder {
 private:
  TestHeapBuilder(const TestHeapBuilder &);
  TestHeapBuilder &operator=(const TestHeapBuilder &);

 public:
  TestHeapBuilder() : FlatBufferBuilder(2048, new OwnedAllocator(), true) {}

  TestHeapBuilder(TestHeapBuilder &&other)
      : FlatBufferBuilder(std::move(other)) {}

  TestHeapBuilder &operator=(TestHeapBuilder &&other) {
    FlatBufferBuilder::operator=(std::move(other));
    return *this;
  }
};

// This class simulates flatbuffers::grpc::detail::SliceAllocatorMember
struct AllocatorMember {
  flatbuffers::DefaultAllocator member_allocator_;
};

struct GrpcLikeMessageBuilder : private AllocatorMember,
                                public FlatBufferBuilder {
 private:
  GrpcLikeMessageBuilder(const GrpcLikeMessageBuilder &);
  GrpcLikeMessageBuilder &operator=(const GrpcLikeMessageBuilder &);

 public:
  GrpcLikeMessageBuilder()
      : FlatBufferBuilder(1024, &member_allocator_, false) {}

  GrpcLikeMessageBuilder(GrpcLikeMessageBuilder &&other)
      : FlatBufferBuilder(1024, &member_allocator_, false) {
    // Default construct and swap idiom.
    Swap(other);
  }

  GrpcLikeMessageBuilder &operator=(GrpcLikeMessageBuilder &&other) {
    // Construct temporary and swap idiom
    GrpcLikeMessageBuilder temp(std::move(other));
    Swap(temp);
    return *this;
  }

  void Swap(GrpcLikeMessageBuilder &other) {
    // No need to swap member_allocator_ because it's stateless.
    FlatBufferBuilder::Swap(other);
    // After swapping the FlatBufferBuilder, we swap back the allocator, which
    // restores the original allocator back in place. This is necessary because
    // MessageBuilder's allocator is its own member (SliceAllocatorMember). The
    // allocator passed to FlatBufferBuilder::vector_downward must point to this
    // member.
    buf_.swap_allocator(other.buf_);
  }
};

flatbuffers::Offset<Monster> populate1(
    flatbuffers::FlatBufferBuilder &builder) {
  auto name_offset = builder.CreateString(m1_name());
  return CreateMonster(builder, nullptr, 0, 0, name_offset, 0, m1_color());
}

flatbuffers::Offset<Monster> populate2(
    flatbuffers::FlatBufferBuilder &builder) {
  auto name_offset = builder.CreateString(m2_name());
  return CreateMonster(builder, nullptr, 0, 0, name_offset, 0, m2_color());
}

uint8_t *release_raw_base(flatbuffers::FlatBufferBuilder &fbb, size_t &size,
                          size_t &offset) {
  return fbb.ReleaseRaw(size, offset);
}

void free_raw(flatbuffers::grpc::MessageBuilder &, uint8_t *) {
  // release_raw_base calls FlatBufferBuilder::ReleaseRaw on the argument
  // MessageBuilder. It's semantically wrong as MessageBuilder has its own
  // ReleaseRaw member function that takes three arguments. In such cases
  // though, ~MessageBuilder() invokes ~SliceAllocator() that takes care of
  // deleting memory as it calls grpc_slice_unref. Obviously, this behavior is
  // very surprising as the pointer returned by FlatBufferBuilder::ReleaseRaw is
  // not valid as soon as MessageBuilder goes out of scope. This problem does
  // not occur with FlatBufferBuilder.
}

void free_raw(flatbuffers::FlatBufferBuilder &, uint8_t *buf) {
  flatbuffers::DefaultAllocator().deallocate(buf, 0);
}

bool verify(const flatbuffers::DetachedBuffer &buf,
            const std::string &expected_name, Color color) {
  const Monster *monster = flatbuffers::GetRoot<Monster>(buf.data());
  return (monster->name()->str() == expected_name) &&
         (monster->color() == color);
}

bool verify(const uint8_t *buf, size_t offset, const std::string &expected_name,
            Color color) {
  const Monster *monster = flatbuffers::GetRoot<Monster>(buf + offset);
  return (monster->name()->str() == expected_name) &&
         (monster->color() == color);
}

bool release_n_verify(flatbuffers::FlatBufferBuilder &fbb,
                      const std::string &expected_name, Color color) {
  flatbuffers::DetachedBuffer buf = fbb.Release();
  return verify(buf, expected_name, color);
}

// forward-declared in test.cpp
void FlatBufferBuilderTest();

void FlatBufferBuilderTest() {
  using flatbuffers::FlatBufferBuilder;

  BuilderTests<FlatBufferBuilder>::all_tests();
  BuilderTests<TestHeapBuilder>::all_tests();
  BuilderTests<GrpcLikeMessageBuilder>::all_tests();

  BuilderReuseTestSelector tests[4] = {
    REUSABLE_AFTER_RELEASE, REUSABLE_AFTER_RELEASE_RAW,
    REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN,
    REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN
  };

  BuilderReuseTests<FlatBufferBuilder, FlatBufferBuilder>::run_tests(
      TestSelector(tests, tests + 4));
  BuilderReuseTests<TestHeapBuilder, TestHeapBuilder>::run_tests(
      TestSelector(tests, tests + 4));
  BuilderReuseTests<GrpcLikeMessageBuilder, GrpcLikeMessageBuilder>::run_tests(
      TestSelector(tests, tests + 4));
}

// forward-declared in test_builder.h
void CheckTestGeneratedIsValid(const MyGame::Example::Color &);

// Link-time check using pointer type.
void CheckTestGeneratedIsValid(const MyGame::Example::Color &) {}
