// Protocol Buffers - Google's data interchange format
// Copyright 2024 Google LLC.  All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

#ifndef GOOGLE_PROTOBUF_COMPILER_HPB_CONTEXT_H__
#define GOOGLE_PROTOBUF_COMPILER_HPB_CONTEXT_H__

#include <string>

#include "absl/strings/ascii.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "absl/types/span.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/io/printer.h"
#include "google/protobuf/io/zero_copy_stream.h"
#include "upb/reflection/def.hpp"
#include "upb_generator/common/cpp_to_upb_def.h"

// Must be last.
#include "upb/port/def.inc"

namespace google {
namespace protobuf {
namespace hpb_generator {

enum class Backend { UPB, CPP };

struct Options {
  Backend backend = Backend::UPB;
  bool strip_feature_includes = false;
  io::AnnotationCollector* annotation_collector = nullptr;
};

/**
 * This Context object will be used throughout hpb generation.
 * It is a thin wrapper around an io::Printer and can be easily extended
 * to support more options.
 *
 * Expected usage is:
 * SomeGenerationFunc(..., Context& context) {
 *   context.Emit({{"some_key", some_computed_val}}, R"cc(
 *   // hpb gencode ...
 *  )cc);
 * }
 */
class Context final {
 public:
  Context(const FileDescriptor* file, io::ZeroCopyOutputStream* stream,
          const Options& options)
      : stream_(stream),
        printer_(stream_,
                 io::Printer::Options('$', options.annotation_collector)),
        options_(options) {
    BuildDefPool(file);
  }

  void Emit(absl::Span<const io::Printer::Sub> vars, absl::string_view format,
            google::protobuf::io::Printer::SourceLocation loc =
                google::protobuf::io::Printer::SourceLocation::current()) {
    printer_.Emit(vars, format, loc);
  }

  void Emit(absl::string_view format,
            google::protobuf::io::Printer::SourceLocation loc =
                google::protobuf::io::Printer::SourceLocation::current()) {
    printer_.Emit(format, loc);
  }

  const Options& options() { return options_; }
  io::Printer& printer() { return printer_; }

  std::string GetLayoutIndex(const FieldDescriptor* field) {
    return absl::StrCat(
        upb::generator::FindBaseFieldDef(pool_, field).layout_index());
  }

  int GetLayoutSize(const Descriptor* descriptor) {
    return upb::generator::FindMessageDef(pool_, descriptor)
        .mini_table()
        ->UPB_PRIVATE(size);
  }

  Context(const Context&) = delete;
  Context& operator=(const Context&) = delete;
  Context(Context&&) = delete;
  Context& operator=(Context&&) = delete;

 private:
  void BuildDefPool(const FileDescriptor* file) {
    upb::generator::AddFile(file, &pool_);
  }

  io::ZeroCopyOutputStream* stream_;
  io::Printer printer_;
  Options options_;
  upb::DefPool pool_;
};

// TODO: b/373438292 - re-house these 4 legacy funcs post io::Printer move
inline std::string ToCIdent(absl::string_view str) {
  return absl::StrReplaceAll(str, {{".", "_"}, {"/", "_"}, {"-", "_"}});
}

inline std::string ToPreproc(absl::string_view str) {
  return absl::AsciiStrToUpper(ToCIdent(str));
}

inline std::string StringifiedBackend(Context& ctx) {
  return ctx.options().backend == Backend::UPB ? "upb" : "cpp";
}

inline void EmitFileWarning(const google::protobuf::FileDescriptor* file, Context& ctx) {
  ctx.Emit({{"file_name", file->name()}, {"backend", StringifiedBackend(ctx)}},
           R"cc(
             /* This file was generated by hpb ($backend$) from the input file:
              *
              *     $file_name$
              *
              * Do not edit -- your changes will be discarded when the file is
              * regenerated. */
           )cc");
}

// TODO: b/457468323 append ::hpb instead of ::protos after namespace swap
inline std::string NamespaceFromPackageName(absl::string_view package_name) {
  return absl::StrCat(absl::StrReplaceAll(package_name, {{".", "::"}}),
                      "::protos");
}

template <typename T>
void WrapNamespace(const google::protobuf::FileDescriptor* file, Context& ctx, T&& body) {
  if (file->package().empty()) {
    body();
  } else {
    ctx.Emit(
        {
            {"body", body},
            {"namespace", NamespaceFromPackageName(file->package())},
        },
        R"cc(
          namespace $namespace$ {

          $body$

          }  // namespace $namespace$
        )cc");
  }
}
}  // namespace hpb_generator
}  // namespace protobuf
}  // namespace google

#include "upb/port/undef.inc"

#endif  // GOOGLE_PROTOBUF_COMPILER_HPB_CONTEXT_H__
