/*
 * Copyright 2021 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef FLATBUFFERS_BFBS_GEN_H_
#define FLATBUFFERS_BFBS_GEN_H_

#include <cstdint>

#include "flatbuffers/code_generator.h"
#include "flatbuffers/reflection_generated.h"

namespace flatbuffers {

namespace {

static void ForAllEnums(
    const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>>* enums,
    std::function<void(const reflection::Enum*)> func) {
  for (auto it = enums->cbegin(); it != enums->cend(); ++it) {
    func(*it);
  }
}

static void ForAllObjects(
    const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>>* objects,
    std::function<void(const reflection::Object*)> func) {
  for (auto it = objects->cbegin(); it != objects->cend(); ++it) {
    func(*it);
  }
}

static void ForAllEnumValues(
    const reflection::Enum* enum_def,
    std::function<void(const reflection::EnumVal*)> func) {
  for (auto it = enum_def->values()->cbegin(); it != enum_def->values()->cend();
       ++it) {
    func(*it);
  }
}

static void ForAllDocumentation(
    const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>*
        documentation,
    std::function<void(const flatbuffers::String*)> func) {
  if (!documentation) {
    return;
  }
  for (auto it = documentation->cbegin(); it != documentation->cend(); ++it) {
    func(*it);
  }
}

// Maps the field index into object->fields() to the field's ID (the ith element
// in the return vector).
static std::vector<uint32_t> FieldIdToIndex(const reflection::Object* object) {
  std::vector<uint32_t> field_index_by_id;
  field_index_by_id.resize(object->fields()->size());

  // Create the mapping of field ID to the index into the vector.
  for (uint32_t i = 0; i < object->fields()->size(); ++i) {
    auto field = object->fields()->Get(i);
    field_index_by_id[field->id()] = i;
  }

  return field_index_by_id;
}

static bool IsStructOrTable(const reflection::BaseType base_type) {
  return base_type == reflection::Obj;
}

static bool IsFloatingPoint(const reflection::BaseType base_type) {
  return base_type == reflection::Float || base_type == reflection::Double;
}

static bool IsBool(const reflection::BaseType base_type) {
  return base_type == reflection::Bool;
}

static bool IsSingleByte(const reflection::BaseType base_type) {
  return base_type >= reflection::UType && base_type <= reflection::UByte;
}

static bool IsVector(const reflection::BaseType base_type) {
  return base_type == reflection::Vector;
}

}  // namespace

// A concrete base Flatbuffer Generator that specific language generators can
// derive from.
class BaseBfbsGenerator : public CodeGenerator {
 public:
  virtual ~BaseBfbsGenerator() {}
  BaseBfbsGenerator() : schema_(nullptr) {}

  virtual Status GenerateFromSchema(const reflection::Schema* schema,
                                    const CodeGenOptions& options) = 0;

  virtual uint64_t SupportedAdvancedFeatures() const = 0;

  // Override of the Generator::GenerateCode method that does the initial
  // deserialization and verification steps.
  Status GenerateCode(const uint8_t* buffer, int64_t length,
                      const CodeGenOptions& options) FLATBUFFERS_OVERRIDE {
    flatbuffers::Verifier verifier(buffer, static_cast<size_t>(length));
    if (!reflection::VerifySchemaBuffer(verifier)) {
      return FAILED_VERIFICATION;
    }

    // Store the root schema since there are cases where leaf nodes refer to
    // things in the root schema (e.g., indexing the objects).
    schema_ = reflection::GetSchema(buffer);

    const uint64_t advance_features = schema_->advanced_features();
    if (advance_features > SupportedAdvancedFeatures()) {
      return FAILED_VERIFICATION;
    }

    Status status = GenerateFromSchema(schema_, options);
    schema_ = nullptr;
    return status;
  }

 protected:
  // GetObject returns the underlying object struct of the given type
  // if element_type is true and GetObject is a list of objects then
  // GetObject will correctly return the object struct of the vector's elements
  const reflection::Object* GetObject(const reflection::Type* type,
                                      bool element_type = false) const {
    const reflection::BaseType base_type =
        element_type ? type->element() : type->base_type();
    if (type->index() >= 0 && IsStructOrTable(base_type)) {
      return GetObjectByIndex(type->index());
    }
    return nullptr;
  }

  // GetEnum returns the underlying enum struct of the given type
  // if element_type is true and GetEnum is a list of enums then
  // GetEnum will correctly return the enum struct of the vector's elements
  const reflection::Enum* GetEnum(const reflection::Type* type,
                                  bool element_type = false) const {
    const reflection::BaseType base_type =
        element_type ? type->element() : type->base_type();
    // TODO(derekbailey): it would be better to have a explicit list of allowed
    // base types, instead of negating Obj types.
    if (type->index() >= 0 && !IsStructOrTable(base_type)) {
      return GetEnumByIndex(type->index());
    }
    return nullptr;
  }

  // Used to get a object that is reference by index. (e.g.
  // reflection::Type::index). Returns nullptr if no object is available.
  const reflection::Object* GetObjectByIndex(int32_t index) const {
    if (!schema_ || index < 0 ||
        index >= static_cast<int32_t>(schema_->objects()->size())) {
      return nullptr;
    }
    return schema_->objects()->Get(index);
  }

  // Used to get a enum that is reference by index. (e.g.
  // reflection::Type::index). Returns nullptr if no enum is available.
  const reflection::Enum* GetEnumByIndex(int32_t index) const {
    if (!schema_ || index < 0 ||
        index >= static_cast<int32_t>(schema_->enums()->size())) {
      return nullptr;
    }
    return schema_->enums()->Get(index);
  }

  void ForAllFields(const reflection::Object* object, bool reverse,
                    std::function<void(const reflection::Field*)> func) const {
    const std::vector<uint32_t> field_to_id_map = FieldIdToIndex(object);
    for (size_t i = 0; i < field_to_id_map.size(); ++i) {
      func(object->fields()->Get(
          field_to_id_map[reverse ? field_to_id_map.size() - (i + 1) : i]));
    }
  }

  bool IsTable(const reflection::Type* type, bool use_element = false) const {
    return !IsStruct(type, use_element);
  }

  bool IsStruct(const reflection::Type* type, bool use_element = false) const {
    const reflection::BaseType base_type =
        use_element ? type->element() : type->base_type();
    return IsStructOrTable(base_type) &&
           GetObjectByIndex(type->index())->is_struct();
  }

  const reflection::Schema* schema_;
};

}  // namespace flatbuffers

#endif  // FLATBUFFERS_BFBS_GEN_H_
