// 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;
};

/**
 * 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_), 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_; }

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

  inline 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:
  inline 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/346865271 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__
