// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <google/protobuf/compiler/objectivec/objectivec_file.h>
#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
#include <google/protobuf/compiler/objectivec/objectivec_message.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/stl_util.h>
#include <google/protobuf/stubs/strutil.h>
#include <algorithm> // std::find()
#include <iostream>
#include <sstream>

// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
// error cases, so it seems to be ok to use as a back door for errors.

namespace google {
namespace protobuf {
namespace compiler {
namespace objectivec {

namespace {

// This is also found in GPBBootstrap.h, and needs to be kept in sync.
const int32 GOOGLE_PROTOBUF_OBJC_VERSION = 30002;

const char* kHeaderExtension = ".pbobjc.h";

// Checks if a message contains any enums definitions (on the message or
// a nested message under it).
bool MessageContainsEnums(const Descriptor* message) {
  if (message->enum_type_count() > 0) {
    return true;
  }
  for (int i = 0; i < message->nested_type_count(); i++) {
    if (MessageContainsEnums(message->nested_type(i))) {
      return true;
    }
  }
  return false;
}

// Checks if a message contains any extension definitions (on the message or
// a nested message under it).
bool MessageContainsExtensions(const Descriptor* message) {
  if (message->extension_count() > 0) {
    return true;
  }
  for (int i = 0; i < message->nested_type_count(); i++) {
    if (MessageContainsExtensions(message->nested_type(i))) {
      return true;
    }
  }
  return false;
}

// Checks if the file contains any enum definitions (at the root or
// nested under a message).
bool FileContainsEnums(const FileDescriptor* file) {
  if (file->enum_type_count() > 0) {
    return true;
  }
  for (int i = 0; i < file->message_type_count(); i++) {
    if (MessageContainsEnums(file->message_type(i))) {
      return true;
    }
  }
  return false;
}

// Checks if the file contains any extensions definitions (at the root or
// nested under a message).
bool FileContainsExtensions(const FileDescriptor* file) {
  if (file->extension_count() > 0) {
    return true;
  }
  for (int i = 0; i < file->message_type_count(); i++) {
    if (MessageContainsExtensions(file->message_type(i))) {
      return true;
    }
  }
  return false;
}

// Helper for CollectMinimalFileDepsContainingExtensionsWorker that marks all
// deps as visited and prunes them from the needed files list.
void PruneFileAndDepsMarkingAsVisited(
    const FileDescriptor* file,
    std::vector<const FileDescriptor*>* files,
    std::set<const FileDescriptor*>* files_visited) {
  std::vector<const FileDescriptor*>::iterator iter =
      std::find(files->begin(), files->end(), file);
  if (iter != files->end()) {
    files->erase(iter);
  }
  files_visited->insert(file);
  for (int i = 0; i < file->dependency_count(); i++) {
    PruneFileAndDepsMarkingAsVisited(file->dependency(i), files, files_visited);
  }
}

// Helper for CollectMinimalFileDepsContainingExtensions.
void CollectMinimalFileDepsContainingExtensionsWorker(
    const FileDescriptor* file,
    std::vector<const FileDescriptor*>* files,
    std::set<const FileDescriptor*>* files_visited) {
  if (files_visited->find(file) != files_visited->end()) {
    return;
  }
  files_visited->insert(file);

  if (FileContainsExtensions(file)) {
    files->push_back(file);
    for (int i = 0; i < file->dependency_count(); i++) {
      const FileDescriptor* dep = file->dependency(i);
      PruneFileAndDepsMarkingAsVisited(dep, files, files_visited);
    }
  } else {
    for (int i = 0; i < file->dependency_count(); i++) {
      const FileDescriptor* dep = file->dependency(i);
      CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
                                                       files_visited);
    }
  }
}

// Collect the deps of the given file that contain extensions. This can be used to
// create the chain of roots that need to be wired together.
//
// NOTE: If any changes are made to this and the supporting functions, you will
// need to manually validate what the generated code is for the test files:
//   objectivec/Tests/unittest_extension_chain_*.proto
// There are comments about what the expected code should be line and limited
// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports
// specifically).
void CollectMinimalFileDepsContainingExtensions(
    const FileDescriptor* file,
    std::vector<const FileDescriptor*>* files) {
  std::set<const FileDescriptor*> files_visited;
  for (int i = 0; i < file->dependency_count(); i++) {
    const FileDescriptor* dep = file->dependency(i);
    CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
                                                     &files_visited);
  }
}

bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) {
  for (int i = 0; i < file->dependency_count(); i++) {
    if (dep == file->dependency(i)) {
      return true;
    }
  }
  return false;
}

}  // namespace

FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options)
    : file_(file),
      root_class_name_(FileClassName(file)),
      is_bundled_proto_(IsProtobufLibraryBundledProtoFile(file)),
      options_(options) {
  for (int i = 0; i < file_->enum_type_count(); i++) {
    EnumGenerator *generator = new EnumGenerator(file_->enum_type(i));
    enum_generators_.push_back(generator);
  }
  for (int i = 0; i < file_->message_type_count(); i++) {
    MessageGenerator *generator =
        new MessageGenerator(root_class_name_, file_->message_type(i), options_);
    message_generators_.push_back(generator);
  }
  for (int i = 0; i < file_->extension_count(); i++) {
    ExtensionGenerator *generator =
        new ExtensionGenerator(root_class_name_, file_->extension(i));
    extension_generators_.push_back(generator);
  }
}

FileGenerator::~FileGenerator() {
  STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
  STLDeleteContainerPointers(message_generators_.begin(),
                             message_generators_.end());
  STLDeleteContainerPointers(extension_generators_.begin(),
                             extension_generators_.end());
}

void FileGenerator::GenerateHeader(io::Printer *printer) {
  std::set<string> headers;
  // Generated files bundled with the library get minimal imports, everything
  // else gets the wrapper so everything is usable.
  if (is_bundled_proto_) {
    headers.insert("GPBRootObject.h");
    headers.insert("GPBMessage.h");
    headers.insert("GPBDescriptor.h");
  } else {
    headers.insert("GPBProtocolBuffers.h");
  }
  PrintFileRuntimePreamble(printer, headers);

  // Add some verification that the generated code matches the source the
  // code is being compiled with.
  // NOTE: This captures the raw numeric values at the time the generator was
  // compiled, since that will be the versions for the ObjC runtime at that
  // time.  The constants in the generated code will then get their values at
  // at compile time (so checking against the headers being used to compile).
  printer->Print(
      "#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n"
      "#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n"
      "#endif\n"
      "#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION\n"
      "#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n"
      "#endif\n"
      "\n",
      "google_protobuf_objc_version", SimpleItoa(GOOGLE_PROTOBUF_OBJC_VERSION));

  // #import any headers for "public imports" in the proto file.
  {
    ImportWriter import_writer(
        options_.generate_for_named_framework,
        options_.named_framework_to_proto_path_mappings_path,
        is_bundled_proto_);
    const string header_extension(kHeaderExtension);
    for (int i = 0; i < file_->public_dependency_count(); i++) {
      import_writer.AddFile(file_->public_dependency(i), header_extension);
    }
    import_writer.Print(printer);
  }

  // Note:
  //  deprecated-declarations suppression is only needed if some place in this
  //    proto file is something deprecated or if it references something from
  //    another file that is deprecated.
  printer->Print(
      "// @@protoc_insertion_point(imports)\n"
      "\n"
      "#pragma clang diagnostic push\n"
      "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"
      "\n"
      "CF_EXTERN_C_BEGIN\n"
      "\n");

  std::set<string> fwd_decls;
  for (std::vector<MessageGenerator *>::iterator iter = message_generators_.begin();
       iter != message_generators_.end(); ++iter) {
    (*iter)->DetermineForwardDeclarations(&fwd_decls);
  }
  for (std::set<string>::const_iterator i(fwd_decls.begin());
       i != fwd_decls.end(); ++i) {
    printer->Print("$value$;\n", "value", *i);
  }
  if (fwd_decls.begin() != fwd_decls.end()) {
    printer->Print("\n");
  }

  printer->Print(
      "NS_ASSUME_NONNULL_BEGIN\n"
      "\n");

  // need to write out all enums first
  for (std::vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
       iter != enum_generators_.end(); ++iter) {
    (*iter)->GenerateHeader(printer);
  }

  for (std::vector<MessageGenerator *>::iterator iter = message_generators_.begin();
       iter != message_generators_.end(); ++iter) {
    (*iter)->GenerateEnumHeader(printer);
  }

  // For extensions to chain together, the Root gets created even if there
  // are no extensions.
  printer->Print(
      "#pragma mark - $root_class_name$\n"
      "\n"
      "/**\n"
      " * Exposes the extension registry for this file.\n"
      " *\n"
      " * The base class provides:\n"
      " * @code\n"
      " *   + (GPBExtensionRegistry *)extensionRegistry;\n"
      " * @endcode\n"
      " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
      " * this file and all files that it depends on.\n"
      " **/\n"
      "@interface $root_class_name$ : GPBRootObject\n"
      "@end\n"
      "\n",
      "root_class_name", root_class_name_);

  if (extension_generators_.size() > 0) {
    // The dynamic methods block is only needed if there are extensions.
    printer->Print(
        "@interface $root_class_name$ (DynamicMethods)\n",
        "root_class_name", root_class_name_);

    for (std::vector<ExtensionGenerator *>::iterator iter =
             extension_generators_.begin();
         iter != extension_generators_.end(); ++iter) {
      (*iter)->GenerateMembersHeader(printer);
    }

    printer->Print("@end\n\n");
  }  // extension_generators_.size() > 0

  for (std::vector<MessageGenerator *>::iterator iter = message_generators_.begin();
       iter != message_generators_.end(); ++iter) {
    (*iter)->GenerateMessageHeader(printer);
  }

  printer->Print(
      "NS_ASSUME_NONNULL_END\n"
      "\n"
      "CF_EXTERN_C_END\n"
      "\n"
      "#pragma clang diagnostic pop\n"
      "\n"
      "// @@protoc_insertion_point(global_scope)\n");
}

void FileGenerator::GenerateSource(io::Printer *printer) {
  // #import the runtime support.
  std::set<string> headers;
  headers.insert("GPBProtocolBuffers_RuntimeSupport.h");
  PrintFileRuntimePreamble(printer, headers);

  // Enums use atomic in the generated code, so add the system import as needed.
  if (FileContainsEnums(file_)) {
    printer->Print(
        "#import <stdatomic.h>\n"
        "\n");
  }

  std::vector<const FileDescriptor*> deps_with_extensions;
  CollectMinimalFileDepsContainingExtensions(file_, &deps_with_extensions);

  {
    ImportWriter import_writer(
        options_.generate_for_named_framework,
        options_.named_framework_to_proto_path_mappings_path,
        is_bundled_proto_);
    const string header_extension(kHeaderExtension);

    // #import the header for this proto file.
    import_writer.AddFile(file_, header_extension);

    // #import the headers for anything that a plain dependency of this proto
    // file (that means they were just an include, not a "public" include).
    std::set<string> public_import_names;
    for (int i = 0; i < file_->public_dependency_count(); i++) {
      public_import_names.insert(file_->public_dependency(i)->name());
    }
    for (int i = 0; i < file_->dependency_count(); i++) {
      const FileDescriptor *dep = file_->dependency(i);
      bool public_import = (public_import_names.count(dep->name()) != 0);
      if (!public_import) {
        import_writer.AddFile(dep, header_extension);
      }
    }

    // If any indirect dependency provided extensions, it needs to be directly
    // imported so it can get merged into the root's extensions registry.
    // See the Note by CollectMinimalFileDepsContainingExtensions before
    // changing this.
    for (std::vector<const FileDescriptor *>::iterator iter =
             deps_with_extensions.begin();
         iter != deps_with_extensions.end(); ++iter) {
      if (!IsDirectDependency(*iter, file_)) {
        import_writer.AddFile(*iter, header_extension);
      }
    }

    import_writer.Print(printer);
  }

  bool includes_oneof = false;
  for (std::vector<MessageGenerator *>::iterator iter = message_generators_.begin();
       iter != message_generators_.end(); ++iter) {
    if ((*iter)->IncludesOneOfDefinition()) {
      includes_oneof = true;
      break;
    }
  }

  // Note:
  //  deprecated-declarations suppression is only needed if some place in this
  //    proto file is something deprecated or if it references something from
  //    another file that is deprecated.
  printer->Print(
      "// @@protoc_insertion_point(imports)\n"
      "\n"
      "#pragma clang diagnostic push\n"
      "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n");
  if (includes_oneof) {
    // The generated code for oneof's uses direct ivar access, suppress the
    // warning incase developer turn that on in the context they compile the
    // generated code.
    printer->Print(
        "#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n");
  }

  printer->Print(
      "\n"
      "#pragma mark - $root_class_name$\n"
      "\n"
      "@implementation $root_class_name$\n\n",
      "root_class_name", root_class_name_);

  const bool file_contains_extensions = FileContainsExtensions(file_);

  // If there were any extensions or this file has any dependencies, output
  // a registry to override to create the file specific registry.
  if (file_contains_extensions || !deps_with_extensions.empty()) {
    printer->Print(
        "+ (GPBExtensionRegistry*)extensionRegistry {\n"
        "  // This is called by +initialize so there is no need to worry\n"
        "  // about thread safety and initialization of registry.\n"
        "  static GPBExtensionRegistry* registry = nil;\n"
        "  if (!registry) {\n"
        "    GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"
        "    registry = [[GPBExtensionRegistry alloc] init];\n");

    printer->Indent();
    printer->Indent();

    if (file_contains_extensions) {
      printer->Print(
          "static GPBExtensionDescription descriptions[] = {\n");
      printer->Indent();
      for (std::vector<ExtensionGenerator *>::iterator iter =
               extension_generators_.begin();
           iter != extension_generators_.end(); ++iter) {
        (*iter)->GenerateStaticVariablesInitialization(printer);
      }
      for (std::vector<MessageGenerator *>::iterator iter =
               message_generators_.begin();
           iter != message_generators_.end(); ++iter) {
        (*iter)->GenerateStaticVariablesInitialization(printer);
      }
      printer->Outdent();
      printer->Print(
          "};\n"
          "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
          "  GPBExtensionDescriptor *extension =\n"
          "      [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]];\n"
          "  [registry addExtension:extension];\n"
          "  [self globallyRegisterExtension:extension];\n"
          "  [extension release];\n"
          "}\n");
    }

    if (deps_with_extensions.empty()) {
      printer->Print(
          "// None of the imports (direct or indirect) defined extensions, so no need to add\n"
          "// them to this registry.\n");
    } else {
      printer->Print(
          "// Merge in the imports (direct or indirect) that defined extensions.\n");
      for (std::vector<const FileDescriptor *>::iterator iter =
               deps_with_extensions.begin();
           iter != deps_with_extensions.end(); ++iter) {
        const string root_class_name(FileClassName((*iter)));
        printer->Print(
            "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
            "dependency", root_class_name);
      }
    }

    printer->Outdent();
    printer->Outdent();

    printer->Print(
        "  }\n"
        "  return registry;\n"
        "}\n");
  } else {
    if (file_->dependency_count() > 0) {
      printer->Print(
          "// No extensions in the file and none of the imports (direct or indirect)\n"
          "// defined extensions, so no need to generate +extensionRegistry.\n");
    } else {
      printer->Print(
          "// No extensions in the file and no imports, so no need to generate\n"
          "// +extensionRegistry.\n");
    }
  }

  printer->Print("\n@end\n\n");

  // File descriptor only needed if there are messages to use it.
  if (message_generators_.size() > 0) {
    std::map<string, string> vars;
    vars["root_class_name"] = root_class_name_;
    vars["package"] = file_->package();
    vars["objc_prefix"] = FileClassPrefix(file_);
    switch (file_->syntax()) {
      case FileDescriptor::SYNTAX_UNKNOWN:
        vars["syntax"] = "GPBFileSyntaxUnknown";
        break;
      case FileDescriptor::SYNTAX_PROTO2:
        vars["syntax"] = "GPBFileSyntaxProto2";
        break;
      case FileDescriptor::SYNTAX_PROTO3:
        vars["syntax"] = "GPBFileSyntaxProto3";
        break;
    }
    printer->Print(vars,
        "#pragma mark - $root_class_name$_FileDescriptor\n"
        "\n"
        "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
        "  // This is called by +initialize so there is no need to worry\n"
        "  // about thread safety of the singleton.\n"
        "  static GPBFileDescriptor *descriptor = NULL;\n"
        "  if (!descriptor) {\n"
        "    GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n");
    if (vars["objc_prefix"].size() > 0) {
      printer->Print(
          vars,
          "    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
          "                                                 objcPrefix:@\"$objc_prefix$\"\n"
          "                                                     syntax:$syntax$];\n");
    } else {
      printer->Print(
          vars,
          "    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
          "                                                     syntax:$syntax$];\n");
    }
    printer->Print(
        "  }\n"
        "  return descriptor;\n"
        "}\n"
        "\n");
  }

  for (std::vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
       iter != enum_generators_.end(); ++iter) {
    (*iter)->GenerateSource(printer);
  }
  for (std::vector<MessageGenerator *>::iterator iter = message_generators_.begin();
       iter != message_generators_.end(); ++iter) {
    (*iter)->GenerateSource(printer);
  }

  printer->Print(
    "\n"
    "#pragma clang diagnostic pop\n"
    "\n"
    "// @@protoc_insertion_point(global_scope)\n");
}

// Helper to print the import of the runtime support at the top of generated
// files. This currently only supports the runtime coming from a framework
// as defined by the official CocoaPod.
void FileGenerator::PrintFileRuntimePreamble(
    io::Printer* printer, const std::set<string>& headers_to_import) const {
  printer->Print(
      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
      "// source: $filename$\n"
      "\n",
      "filename", file_->name());

  const string framework_name(ProtobufLibraryFrameworkName);
  const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));

  printer->Print(
      "// This CPP symbol can be defined to use imports that match up to the framework\n"
      "// imports needed when using CocoaPods.\n"
      "#if !defined($cpp_symbol$)\n"
      " #define $cpp_symbol$ 0\n"
      "#endif\n"
      "\n"
      "#if $cpp_symbol$\n",
      "cpp_symbol", cpp_symbol);


  for (std::set<string>::const_iterator iter = headers_to_import.begin();
       iter != headers_to_import.end(); ++iter) {
    printer->Print(
        " #import <$framework_name$/$header$>\n",
        "header", *iter,
        "framework_name", framework_name);
  }

  printer->Print(
      "#else\n");

  for (std::set<string>::const_iterator iter = headers_to_import.begin();
       iter != headers_to_import.end(); ++iter) {
    printer->Print(
        " #import \"$header$\"\n",
        "header", *iter);
  }

  printer->Print(
      "#endif\n"
      "\n");
}

}  // namespace objectivec
}  // namespace compiler
}  // namespace protobuf
}  // namespace google
