// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "rs_bindings_from_cc/generate_bindings_and_metadata.h"

#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/check.h"
#include "absl/strings/string_view.h"
#include "common/status_macros.h"
#include "rs_bindings_from_cc/cmdline.h"
#include "rs_bindings_from_cc/collect_instantiations.h"
#include "rs_bindings_from_cc/collect_namespaces.h"
#include "rs_bindings_from_cc/ir.h"
#include "rs_bindings_from_cc/ir_from_cc.h"
#include "rs_bindings_from_cc/src_code_gen.h"

namespace crubit {

std::optional<const Namespace*> FindNamespace(const IR& ir,
                                              absl::string_view name) {
  for (const auto* ns : ir.get_items_if<Namespace>()) {
    if (ns->name.Ident() == kInstantiationsNamespaceName) {
      return ns;
    }
  }
  return std::nullopt;
}

std::vector<const Record*> FindInstantiationsInNamespace(const IR& ir,
                                                         ItemId namespace_id) {
  absl::flat_hash_set<ItemId> record_ids;
  for (const auto* type_alias : ir.get_items_if<TypeAlias>()) {
    if (type_alias->enclosing_item_id == namespace_id) {
      const MappedType* mapped_type = &type_alias->underlying_type;
      CHECK(mapped_type->cpp_type.decl_id.has_value());
      CHECK(mapped_type->rs_type.decl_id.has_value());
      CHECK(mapped_type->cpp_type.decl_id.value() ==
            mapped_type->rs_type.decl_id.value());
      record_ids.insert(mapped_type->rs_type.decl_id.value());
    }
  }

  std::vector<const Record*> result;
  for (const auto* record : ir.get_items_if<Record>()) {
    if (record_ids.find(record->id) != record_ids.end()) {
      result.push_back(record);
    }
  }
  return result;
}

absl::StatusOr<BindingsAndMetadata> GenerateBindingsAndMetadata(
    Cmdline& cmdline, std::vector<std::string> clang_args,
    absl::flat_hash_map<HeaderName, std::string>
        virtual_headers_contents_for_testing) {
  std::vector<absl::string_view> clang_args_view;
  clang_args_view.insert(clang_args_view.end(), clang_args.begin(),
                         clang_args.end());
  const CmdlineArgs& args = cmdline.args();

  CRUBIT_ASSIGN_OR_RETURN(
      std::vector<std::string> requested_instantiations,
      CollectInstantiations(args.srcs_to_scan_for_instantiations));

  CRUBIT_ASSIGN_OR_RETURN(
      IR ir, IrFromCc(IrFromCcOptions{
                 .current_target = args.current_target,
                 .public_headers = args.public_headers,
                 .virtual_headers_contents_for_testing =
                     std::move(virtual_headers_contents_for_testing),
                 .headers_to_targets = args.headers_to_targets,
                 .extra_rs_srcs = args.extra_rs_srcs,
                 .clang_args = clang_args_view,
                 .extra_instantiations = requested_instantiations,
                 .crubit_features = args.target_to_features}));

  if (!args.instantiations_out.empty()) {
    ir.crate_root_path = "__cc_template_instantiations_rs_api";
  }

  bool generate_error_report = !args.error_report_out.empty();
  CRUBIT_ASSIGN_OR_RETURN(
      Bindings bindings,
      GenerateBindings(ir, args.crubit_support_path_format,
                       args.clang_format_exe_path, args.rustfmt_exe_path,
                       args.rustfmt_config_path, generate_error_report,
                       args.generate_source_location_in_doc_comment));

  absl::flat_hash_map<std::string, std::string> instantiations;
  std::optional<const Namespace*> ns =
      FindNamespace(ir, kInstantiationsNamespaceName);
  if (ns.has_value()) {
    std::vector<const Record*> records =
        FindInstantiationsInNamespace(ir, ns.value()->id);
    for (const auto* record : records) {
      instantiations.insert({record->cc_name, record->rs_name});
    }
  }

  auto top_level_namespaces = crubit::CollectNamespaces(ir);

  return BindingsAndMetadata{
      .ir = ir,
      .rs_api = bindings.rs_api,
      .rs_api_impl = bindings.rs_api_impl,
      .namespaces = std::move(top_level_namespaces),
      .instantiations = std::move(instantiations),
      .error_report = bindings.error_report,
  };
}

}  // namespace crubit
