/*
 * Copyright 2014 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_CODE_GENERATORS_H_
#define FLATBUFFERS_CODE_GENERATORS_H_

namespace flatbuffers {

class BaseGenerator {
 public:
  virtual bool generate() = 0;

  static const std::string NamespaceDir(const Parser &parser,
                                        const std::string &path,
                                        const Namespace &ns) {
    EnsureDirExists(path.c_str());
    if (parser.opts.one_file) return path;
    std::string namespace_dir = path;  // Either empty or ends in separator.
    auto &namespaces = ns.components;
    for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
      namespace_dir += *it + kPathSeparator;
      EnsureDirExists(namespace_dir.c_str());
    }
    return namespace_dir;
  }

 protected:
  BaseGenerator(const Parser &parser, const std::string &path,
                const std::string &file_name,
                const std::string qualifying_start,
                const std::string qualifying_separator)
      : parser_(parser),
        path_(path),
        file_name_(file_name),
        qualifying_start_(qualifying_start),
        qualifying_separator_(qualifying_separator){};
  virtual ~BaseGenerator(){};

  // No copy/assign.
  BaseGenerator &operator=(const BaseGenerator &);
  BaseGenerator(const BaseGenerator &);

  const std::string NamespaceDir(const Namespace &ns) {
    return BaseGenerator::NamespaceDir(parser_, path_, ns);
  }

  const char *FlatBuffersGeneratedWarning() {
    return "automatically generated by the FlatBuffers compiler,"
           " do not modify\n\n";
  }

  bool IsEverythingGenerated() {
    for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
         ++it) {
      if (!(*it)->generated) return false;
    }
    for (auto it = parser_.structs_.vec.begin();
         it != parser_.structs_.vec.end(); ++it) {
      if (!(*it)->generated) return false;
    }
    return true;
  }

  std::string FullNamespace(const char *separator, const Namespace &ns) {
    std::string namespace_name;
    auto &namespaces = ns.components;
    for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
      if (namespace_name.length()) namespace_name += separator;
      namespace_name += *it;
    }
    return namespace_name;
  }

  const std::string LastNamespacePart(const Namespace &ns) {
    auto &namespaces = ns.components;
    if (namespaces.size())
      return *(namespaces.end() - 1);
    else
      return std::string("");
  }

  // tracks the current namespace for early exit in WrapInNameSpace
  // c++, java and csharp returns a different namespace from
  // the following default (no early exit, always fully qualify),
  // which works for js and php
  virtual const Namespace *CurrentNameSpace() { return nullptr; }

  // Ensure that a type is prefixed with its namespace whenever it is used
  // outside of its namespace.
  std::string WrapInNameSpace(const Namespace *ns, const std::string &name) {
    if (CurrentNameSpace() == ns) return name;
    std::string qualified_name = qualifying_start_;
    for (auto it = ns->components.begin(); it != ns->components.end(); ++it)
      qualified_name += *it + qualifying_separator_;
    return qualified_name + name;
  }

  std::string WrapInNameSpace(const Definition &def) {
    return WrapInNameSpace(def.defined_namespace, def.name);
  }

  const Parser &parser_;
  const std::string &path_;
  const std::string &file_name_;
  const std::string qualifying_start_;
  const std::string qualifying_separator_;
};

}  // namespace flatbuffers

#endif  // FLATBUFFERS_CODE_GENERATORS_H_
