/*
 * 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.
 */

// independent from idl_parser, since this code is not needed for most clients

#include <cstdio>

#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include "src/compiler/cpp_generator.h"
#include "src/compiler/go_generator.h"
#include "src/compiler/java_generator.h"
#include "src/compiler/python_generator.h"
#include "src/compiler/swift_generator.h"
#include "src/compiler/ts_generator.h"

#if defined(_MSC_VER)
#  pragma warning(push)
#  pragma warning(disable : 4512)  // C4512: 'class' : assignment operator could
// not be generated
#endif

namespace flatbuffers {

class FlatBufMethod : public grpc_generator::Method {
 public:
  enum Streaming { kNone, kClient, kServer, kBiDi };

  FlatBufMethod(const RPCCall *method) : method_(method) {
    streaming_ = kNone;
    auto val = method_->attributes.Lookup("streaming");
    if (val) {
      if (val->constant == "client") streaming_ = kClient;
      if (val->constant == "server") streaming_ = kServer;
      if (val->constant == "bidi") streaming_ = kBiDi;
    }
  }

  grpc::string GetLeadingComments(const grpc::string) const { return ""; }

  grpc::string GetTrailingComments(const grpc::string) const { return ""; }

  std::vector<grpc::string> GetAllComments() const {
    return method_->doc_comment;
  }

  std::string name() const { return method_->name; }

  // TODO: This method need to incorporate namespace for C++ side. Other
  // language bindings simply don't use this method.
  std::string GRPCType(const StructDef &sd) const {
    return "flatbuffers::grpc::Message<" + sd.name + ">";
  }

  std::vector<std::string> get_input_namespace_parts() const {
    return (*method_->request).defined_namespace->components;
  }

  std::string get_input_type_name() const { return (*method_->request).name; }

  std::vector<std::string> get_output_namespace_parts() const {
    return (*method_->response).defined_namespace->components;
  }

  std::string get_output_type_name() const { return (*method_->response).name; }

  bool get_module_and_message_path_input(grpc::string * /*str*/,
                                         grpc::string /*generator_file_name*/,
                                         bool /*generate_in_pb2_grpc*/,
                                         grpc::string /*import_prefix*/) const {
    return true;
  }

  bool get_module_and_message_path_output(
      grpc::string * /*str*/, grpc::string /*generator_file_name*/,
      bool /*generate_in_pb2_grpc*/, grpc::string /*import_prefix*/) const {
    return true;
  }

  std::string get_fb_builder() const { return "builder"; }

  std::string input_type_name() const { return GRPCType(*method_->request); }

  std::string output_type_name() const { return GRPCType(*method_->response); }

  bool NoStreaming() const { return streaming_ == kNone; }

  bool ClientStreaming() const { return streaming_ == kClient; }

  bool ServerStreaming() const { return streaming_ == kServer; }

  bool BidiStreaming() const { return streaming_ == kBiDi; }

 private:
  const RPCCall *method_;
  Streaming streaming_;
};

class FlatBufService : public grpc_generator::Service {
 public:
  FlatBufService(const ServiceDef *service) : service_(service) {}

  grpc::string GetLeadingComments(const grpc::string) const { return ""; }

  grpc::string GetTrailingComments(const grpc::string) const { return ""; }

  std::vector<grpc::string> GetAllComments() const {
    return service_->doc_comment;
  }

  std::vector<grpc::string> namespace_parts() const {
    return service_->defined_namespace->components;
  }

  std::string name() const { return service_->name; }
  bool is_internal() const {
    return service_->Definition::attributes.Lookup("private") ? true : false;
  }

  int method_count() const {
    return static_cast<int>(service_->calls.vec.size());
  }

  std::unique_ptr<const grpc_generator::Method> method(int i) const {
    return std::unique_ptr<const grpc_generator::Method>(
        new FlatBufMethod(service_->calls.vec[i]));
  }

 private:
  const ServiceDef *service_;
};

class FlatBufPrinter : public grpc_generator::Printer {
 public:
  FlatBufPrinter(std::string *str, const char indentation_type)
      : str_(str),
        escape_char_('$'),
        indent_(0),
        indentation_size_(2),
        indentation_type_(indentation_type) {}

  void Print(const std::map<std::string, std::string> &vars,
             const char *string_template) {
    std::string s = string_template;
    // Replace any occurrences of strings in "vars" that are surrounded
    // by the escape character by what they're mapped to.
    size_t pos;
    while ((pos = s.find(escape_char_)) != std::string::npos) {
      // Found an escape char, must also find the closing one.
      size_t pos2 = s.find(escape_char_, pos + 1);
      // If placeholder not closed, ignore.
      if (pos2 == std::string::npos) break;
      auto it = vars.find(s.substr(pos + 1, pos2 - pos - 1));
      // If unknown placeholder, ignore.
      if (it == vars.end()) break;
      // Subtitute placeholder.
      s.replace(pos, pos2 - pos + 1, it->second);
    }
    Print(s.c_str());
  }

  void Print(const char *s) {
    if (s == nullptr || *s == '\0') { return; }
    // Add this string, but for each part separated by \n, add indentation.
    for (;;) {
      // Current indentation.
      str_->insert(str_->end(), indent_ * indentation_size_, indentation_type_);
      // See if this contains more than one line.
      const char *lf = strchr(s, '\n');
      if (lf) {
        (*str_) += std::string(s, lf + 1);
        s = lf + 1;
        if (!*s) break;  // Only continue if there's more lines.
      } else {
        (*str_) += s;
        break;
      }
    }
  }

  void SetIndentationSize(const size_t size) {
    FLATBUFFERS_ASSERT(str_->empty());
    indentation_size_ = size;
  }

  void Indent() { indent_++; }

  void Outdent() {
    FLATBUFFERS_ASSERT(indent_ > 0);
    indent_--;
  }

 private:
  std::string *str_;
  char escape_char_;
  size_t indent_;
  size_t indentation_size_;
  char indentation_type_;
};

class FlatBufFile : public grpc_generator::File {
 public:
  enum Language {
    kLanguageGo,
    kLanguageCpp,
    kLanguageJava,
    kLanguagePython,
    kLanguageSwift,
    kLanguageTS
  };

  FlatBufFile(const Parser &parser, const std::string &file_name,
              Language language)
      : parser_(parser), file_name_(file_name), language_(language) {}

  FlatBufFile &operator=(const FlatBufFile &);

  grpc::string GetLeadingComments(const grpc::string) const { return ""; }

  grpc::string GetTrailingComments(const grpc::string) const { return ""; }

  std::vector<grpc::string> GetAllComments() const {
    return std::vector<grpc::string>();
  }

  std::string filename() const { return file_name_; }

  std::string filename_without_ext() const {
    return StripExtension(file_name_);
  }

  std::string package() const {
    return parser_.current_namespace_->GetFullyQualifiedName("");
  }

  std::vector<std::string> package_parts() const {
    return parser_.current_namespace_->components;
  }

  std::string additional_headers() const {
    switch (language_) {
      case kLanguageCpp: {
        if (!parser_.opts.grpc_additional_headers.empty()) {
          std::string result = "";
          for (const std::string &header :
               parser_.opts.grpc_additional_headers) {
            if (!result.empty()) result += "\n";
            result += "#include \"" + header + "\"";
          }
          return result;
        }
        return "#include \"flatbuffers/grpc.h\"\n";
      }
      case kLanguageGo: {
        return "import \"github.com/google/flatbuffers/go\"";
      }
      case kLanguageJava: {
        return "import com.google.flatbuffers.grpc.FlatbuffersUtils;";
      }
      case kLanguagePython: {
        return "";
      }
      case kLanguageSwift: {
        return "";
      }
      case kLanguageTS: {
        return "";
      }
    }
    return "";
  }

  int service_count() const {
    return static_cast<int>(parser_.services_.vec.size());
  }

  std::unique_ptr<const grpc_generator::Service> service(int i) const {
    return std::unique_ptr<const grpc_generator::Service>(
        new FlatBufService(parser_.services_.vec[i]));
  }

  std::unique_ptr<grpc_generator::Printer> CreatePrinter(
      std::string *str, const char indentation_type = ' ') const {
    return std::unique_ptr<grpc_generator::Printer>(
        new FlatBufPrinter(str, indentation_type));
  }

 private:
  const Parser &parser_;
  const std::string &file_name_;
  const Language language_;
};

class GoGRPCGenerator : public flatbuffers::BaseGenerator {
 public:
  GoGRPCGenerator(const Parser &parser, const std::string &path,
                  const std::string &file_name)
      : BaseGenerator(parser, path, file_name, "", "" /*Unused*/, "go"),
        parser_(parser),
        path_(path),
        file_name_(file_name) {}

  bool generate() {
    FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguageGo);
    grpc_go_generator::Parameters p;
    p.custom_method_io_type = "flatbuffers.Builder";
    for (int i = 0; i < file.service_count(); i++) {
      auto service = file.service(i);
      const Definition *def = parser_.services_.vec[i];
      p.package_name = LastNamespacePart(*(def->defined_namespace));
      p.service_prefix =
          def->defined_namespace->GetFullyQualifiedName("");  // file.package();
      std::string output =
          grpc_go_generator::GenerateServiceSource(&file, service.get(), &p);
      std::string filename =
          NamespaceDir(*def->defined_namespace) + def->name + "_grpc.go";
      if (!flatbuffers::SaveFile(filename.c_str(), output, false)) return false;
    }
    return true;
  }

 protected:
  const Parser &parser_;
  const std::string &path_, &file_name_;
};

bool GenerateGoGRPC(const Parser &parser, const std::string &path,
                    const std::string &file_name) {
  int nservices = 0;
  for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
       ++it) {
    if (!(*it)->generated) nservices++;
  }
  if (!nservices) return true;
  return GoGRPCGenerator(parser, path, file_name).generate();
}

bool GenerateCppGRPC(const Parser &parser, const std::string &path,
                     const std::string &file_name) {
  const auto &opts = parser.opts;
  int nservices = 0;
  for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
       ++it) {
    if (!(*it)->generated) nservices++;
  }
  if (!nservices) return true;

  std::string suffix = "";
  suffix += opts.filename_suffix.empty() ? "_generated" : opts.filename_suffix;
  suffix += ".";
  suffix += opts.filename_extension.empty() ? "h" : opts.filename_extension;

  grpc_cpp_generator::Parameters generator_parameters;
  // TODO(wvo): make the other parameters in this struct configurable.
  generator_parameters.use_system_headers = opts.grpc_use_system_headers;
  generator_parameters.message_header_extension = suffix;
  generator_parameters.service_header_extension =
      ".grpc" + opts.grpc_filename_suffix + ".h";
  generator_parameters.grpc_search_path = opts.grpc_search_path;
  std::string filename = flatbuffers::StripExtension(parser.file_being_parsed_);
  if (!opts.keep_prefix) {
    filename = flatbuffers::StripPath(filename);
  }
  FlatBufFile fbfile(parser, filename, FlatBufFile::kLanguageCpp);

  std::string header_code =
      grpc_cpp_generator::GetHeaderPrologue(&fbfile, generator_parameters) +
      grpc_cpp_generator::GetHeaderIncludes(&fbfile, generator_parameters) +
      grpc_cpp_generator::GetHeaderServices(&fbfile, generator_parameters) +
      grpc_cpp_generator::GetHeaderEpilogue(&fbfile, generator_parameters);

  std::string source_code =
      grpc_cpp_generator::GetSourcePrologue(&fbfile, generator_parameters) +
      grpc_cpp_generator::GetSourceIncludes(&fbfile, generator_parameters) +
      grpc_cpp_generator::GetSourceServices(&fbfile, generator_parameters) +
      grpc_cpp_generator::GetSourceEpilogue(&fbfile, generator_parameters);

  return flatbuffers::SaveFile(
             (path + file_name + ".grpc" + opts.grpc_filename_suffix + ".h")
                 .c_str(),
             header_code, false) &&
         flatbuffers::SaveFile(
             (path + file_name + ".grpc" + opts.grpc_filename_suffix + ".cc")
                 .c_str(),
             source_code, false);
}

class JavaGRPCGenerator : public flatbuffers::BaseGenerator {
 public:
  JavaGRPCGenerator(const Parser &parser, const std::string &path,
                    const std::string &file_name)
      : BaseGenerator(parser, path, file_name, "", "." /*separator*/, "java") {}

  bool generate() {
    FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguageJava);
    grpc_java_generator::Parameters p;
    for (int i = 0; i < file.service_count(); i++) {
      auto service = file.service(i);
      const Definition *def = parser_.services_.vec[i];
      p.package_name =
          def->defined_namespace->GetFullyQualifiedName("");  // file.package();
      std::string output =
          grpc_java_generator::GenerateServiceSource(&file, service.get(), &p);
      std::string filename =
          NamespaceDir(*def->defined_namespace) + def->name + "Grpc.java";
      if (!flatbuffers::SaveFile(filename.c_str(), output, false)) return false;
    }
    return true;
  }
};

bool GenerateJavaGRPC(const Parser &parser, const std::string &path,
                      const std::string &file_name) {
  int nservices = 0;
  for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
       ++it) {
    if (!(*it)->generated) nservices++;
  }
  if (!nservices) return true;
  return JavaGRPCGenerator(parser, path, file_name).generate();
}

bool GeneratePythonGRPC(const Parser &parser, const std::string &path,
                        const std::string & /*file_name*/) {
  int nservices = 0;
  for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
       ++it) {
    if (!(*it)->generated) nservices++;
  }
  if (!nservices) return true;

  flatbuffers::python::Version version{parser.opts.python_version};
  if (!version.IsValid()) return false;

  if (!flatbuffers::python::grpc::Generate(parser, path, version)) {
    return false;
  }
  if (parser.opts.python_typing) {
    return flatbuffers::python::grpc::GenerateStub(parser, path, version);
  }
  return true;
}

class SwiftGRPCGenerator : public flatbuffers::BaseGenerator {
 private:
  CodeWriter code_;

 public:
  SwiftGRPCGenerator(const Parser &parser, const std::string &path,
                     const std::string &filename)
      : BaseGenerator(parser, path, filename, "", "" /*Unused*/, "swift") {}

  bool generate() {
    code_.Clear();
    code_ += "// Generated GRPC code for FlatBuffers swift!";
    code_ += grpc_swift_generator::GenerateHeader();
    FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguageSwift);
    for (int i = 0; i < file.service_count(); i++) {
      auto service = file.service(i);
      code_ += grpc_swift_generator::Generate(&file, service.get());
    }
    const auto final_code = code_.ToString();
    const auto filename = GeneratedFileName(path_, file_name_);
    return SaveFile(filename.c_str(), final_code, false);
  }

  static std::string GeneratedFileName(const std::string &path,
                                       const std::string &file_name) {
    return path + file_name + ".grpc.swift";
  }
};

bool GenerateSwiftGRPC(const Parser &parser, const std::string &path,
                       const std::string &file_name) {
  int nservices = 0;
  for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
       ++it) {
    if (!(*it)->generated) nservices++;
  }
  if (!nservices) return true;
  return SwiftGRPCGenerator(parser, path, file_name).generate();
}

class TSGRPCGenerator : public flatbuffers::BaseGenerator {
 private:
  CodeWriter code_;

 public:
  TSGRPCGenerator(const Parser &parser, const std::string &path,
                  const std::string &filename)
      : BaseGenerator(parser, path, filename, "", "" /*Unused*/, "ts") {}

  bool generate() {
    code_.Clear();
    FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguageTS);

    for (int i = 0; i < file.service_count(); i++) {
      auto service = file.service(i);
      code_ += grpc_ts_generator::Generate(&file, service.get(), file_name_);
      const auto ts_name = GeneratedFileName(path_, file_name_);
      if (!SaveFile(ts_name.c_str(), code_.ToString(), false)) return false;

      code_.Clear();
      code_ += grpc_ts_generator::GenerateInterface(&file, service.get(),
                                                    file_name_);
      const auto ts_interface_name = GeneratedFileName(path_, file_name_, true);
      if (!SaveFile(ts_interface_name.c_str(), code_.ToString(), false))
        return false;
    }
    return true;
  }

  static std::string GeneratedFileName(const std::string &path,
                                       const std::string &file_name,
                                       const bool is_interface = false) {
    if (is_interface) return path + file_name + "_grpc.d.ts";
    return path + file_name + "_grpc.js";
  }
};

bool GenerateTSGRPC(const Parser &parser, const std::string &path,
                    const std::string &file_name) {
  int nservices = 0;
  for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
       ++it) {
    if (!(*it)->generated) nservices++;
  }
  if (!nservices) return true;
  return TSGRPCGenerator(parser, path, file_name).generate();
}

}  // namespace flatbuffers

#if defined(_MSC_VER)
#  pragma warning(pop)
#endif
