// Copyright 2026 Google LLC
//
// 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
//
//    https://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.
//

#include "cbor/cbor_generator.h"

#include <memory>
#include <string>

#include "absl/base/no_destructor.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/string_view.h"
#include "cbor/tags.pb.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/io/printer.h"
#include "google/protobuf/io/zero_copy_stream.h"

namespace cbor {
namespace {

std::string QualifiedCppName(const google::protobuf::Descriptor* descriptor) {
  return absl::StrReplaceAll(descriptor->full_name(), {{".", "::"}});
}

absl::string_view StripProtoExtension(absl::string_view filename) {
  if (absl::EndsWith(filename, ".proto")) {
    return filename.substr(0, filename.size() - 6);
  }
  return filename;
}

const cbor::Tags& GetTags(const google::protobuf::FieldDescriptor* field) {
  if (field->options().HasExtension(cbor::tags)) {
    return field->options().GetExtension(cbor::tags);
  }
  static const absl::NoDestructor<cbor::Tags> default_tags;
  return *default_tags;
}

std::string GetCborKey(const google::protobuf::FieldDescriptor* field) {
  const auto& tags = GetTags(field);
  if (!tags.name().empty()) {
    return std::string(tags.name());
  }
  return std::string(field->name());
}

const absl::flat_hash_map<google::protobuf::FieldDescriptor::Type,
                          absl::string_view>&
GetProtoTypeToCborType() {
  static const absl::NoDestructor<absl::flat_hash_map<
      google::protobuf::FieldDescriptor::Type, absl::string_view>>
      proto_type_to_cbor_type({
          {google::protobuf::FieldDescriptor::TYPE_MESSAGE, "Map"},
          {google::protobuf::FieldDescriptor::TYPE_STRING, "String"},
          {google::protobuf::FieldDescriptor::TYPE_UINT64, "Uint64"},
          {google::protobuf::FieldDescriptor::TYPE_INT64, "Int64"},
          {google::protobuf::FieldDescriptor::TYPE_UINT32, "Uint64"},
          {google::protobuf::FieldDescriptor::TYPE_INT32, "Int64"},
          {google::protobuf::FieldDescriptor::TYPE_BOOL, "Bool"},
          {google::protobuf::FieldDescriptor::TYPE_FLOAT, "Float"},
          {google::protobuf::FieldDescriptor::TYPE_DOUBLE, "Double"},
          {google::protobuf::FieldDescriptor::TYPE_BYTES, "ByteString"},
      });
  return *proto_type_to_cbor_type;
}

absl::string_view GetCborTypeName(
    const google::protobuf::FieldDescriptor* field) {
  const auto& tags = GetTags(field);
  if (tags.type() != cbor::Tags::TYPE_UNSPECIFIED) {
    switch (tags.type()) {
      case cbor::Tags::TYPE_UINT:
        return "Uint64";
      case cbor::Tags::TYPE_NINT:
        return "Int64";
      case cbor::Tags::TYPE_BYTE_STRING:
        return "ByteString";
      case cbor::Tags::TYPE_TEXT_STRING:
        return "String";
      default:
        break;
    }
  }
  auto it = GetProtoTypeToCborType().find(field->type());
  if (it != GetProtoTypeToCborType().end()) {
    return it->second;
  }
  return "";
}

void GenerateMessageHeader(const google::protobuf::Descriptor* desc,
                           google::protobuf::io::Printer& printer) {
  printer.Emit({{"name", QualifiedCppName(desc)}}, R"cc(
    absl::Status ToProto(const cbor::MapView& map, $name$* proto);
    absl::StatusOr<std::unique_ptr<cppbor::Map>> FromProto(const $name$& proto);
    absl::StatusOr<std::unique_ptr<cppbor::Map>> FromProto(
        const $name$& proto, FromProtoOptions options);
  )cc");
  for (int i = 0; i < desc->nested_type_count(); ++i) {
    GenerateMessageHeader(desc->nested_type(i), printer);
  }
}

void GenerateToProtoBody(const google::protobuf::Descriptor* desc,
                         google::protobuf::io::Printer& printer) {
  printer.Emit({{"name", QualifiedCppName(desc)}}, R"cc(
    absl::Status ToProto(const cbor::MapView& map, $name$* proto) {
  )cc");
  {
    auto indent = printer.WithIndent();
    for (int i = 0; i < desc->field_count(); ++i) {
      const auto* field = desc->field(i);
      const auto& tags = GetTags(field);
      if (tags.mode() == cbor::Tags::MODE_WRITE_ONLY ||
          tags.mode() == cbor::Tags::MODE_SKIP) {
        continue;
      }

      std::string key = GetCborKey(field);
      printer.Emit(R"cc(
        {
      )cc");
      {
        auto scope_indent = printer.WithIndent();
        if (field->is_repeated()) {
          if (field->type() ==
              google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
            printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
              auto array_view = map.GetOptionalArray("$key$");
            )cc");
            if (tags.is_required()) {
              printer.Emit({{"key", key}}, R"cc(
                if (!array_view.has_value()) {
                  return absl::InvalidArgumentError(
                      "Missing required field: "
                      "$key$");
                }
              )cc");
            }
            if (tags.disallow_empty()) {
              printer.Emit({{"key", key}}, R"cc(
                if (array_view.has_value() && array_view->size() == 0) {
                  return absl::InvalidArgumentError(
                      "Field $key$ cannot be "
                      "empty");
                }
              )cc");
            }
            printer.Emit({{"field", field->name()}}, R"cc(
              if (array_view.has_value()) {
                for (uint32_t i = 0; i < array_view->size(); ++i) {
                  ABSL_ASSIGN_OR_RETURN(auto item, array_view->GetMap(i));
                  ABSL_RETURN_IF_ERROR(ToProto(std::move(item), proto->add_$field$()));
                }
              }
            )cc");
          } else if (!GetCborTypeName(field).empty()) {
            absl::string_view type = GetCborTypeName(field);
            printer.Emit(
                {{"field", field->name()}, {"key", key}, {"type", type}}, R"cc(
                  auto array_view = map.GetOptionalArray("$key$");
                )cc");
            if (tags.is_required()) {
              printer.Emit({{"key", key}}, R"cc(
                if (!array_view.has_value()) {
                  return absl::InvalidArgumentError(
                      "Missing required field: "
                      "$key$");
                }
              )cc");
            }
            if (tags.disallow_empty()) {
              printer.Emit({{"key", key}}, R"cc(
                if (array_view.has_value() && array_view->size() == 0) {
                  return absl::InvalidArgumentError(
                      "Field $key$ cannot be "
                      "empty");
                }
              )cc");
            }
            printer.Emit({{"field", field->name()}, {"type", type}}, R"cc(
              if (array_view.has_value()) {
                for (uint32_t i = 0; i < array_view->size(); ++i) {
                  ABSL_ASSIGN_OR_RETURN(auto item, array_view->Get$type$(i));
                  proto->add_$field$(std::move(item));
                }
              }
            )cc");
          }
        } else {
          if (field->type() ==
              google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
            if (tags.is_required()) {
              printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
                auto map_view = map.GetOptionalMap("$key$");
                if (!map_view.has_value()) {
                  return absl::InvalidArgumentError(
                      "Missing required field: "
                      "$key$");
                }
                ABSL_RETURN_IF_ERROR(ToProto(*map_view, proto->mutable_$field$()));
              )cc");
            } else {
              printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
                auto map_view = map.GetOptionalMap("$key$");
                if (map_view.has_value()) {
                  ABSL_RETURN_IF_ERROR(ToProto(*map_view, proto->mutable_$field$()));
                }
              )cc");
            }
          } else if (!GetCborTypeName(field).empty()) {
            absl::string_view type = GetCborTypeName(field);
            if (tags.is_required()) {
              printer.Emit(
                  {{"field", field->name()}, {"key", key}, {"type", type}},
                  R"cc(
                    auto val = map.GetOptional$type$("$key$");
                    if (!val.has_value()) {
                      return absl::InvalidArgumentError(
                          "Missing required "
                          "field: $key$");
                    }
                    proto->set_$field$(*val);
                  )cc");
            } else {
              printer.Emit(
                  {{"field", field->name()}, {"key", key}, {"type", type}},
                  R"cc(
                    auto val = map.GetOptional$type$("$key$");
                    if (val.has_value()) {
                      proto->set_$field$(*val);
                    }
                  )cc");
            }
          }
        }
      }
      printer.Emit(R"cc(
        }
      )cc");
    }
    printer.Emit(R"cc(
      return absl::OkStatus();
    )cc");
  }
  printer.Emit(R"cc(
    }
  )cc");
  for (int i = 0; i < desc->nested_type_count(); ++i) {
    GenerateToProtoBody(desc->nested_type(i), printer);
  }
}

void GenerateFromProtoBody(const google::protobuf::Descriptor* desc,
                           google::protobuf::io::Printer& printer) {
  printer.Emit({{"name", QualifiedCppName(desc)}}, R"cc(
    absl::StatusOr<std::unique_ptr<cppbor::Map>> FromProto(
        const $name$& proto) {
      return FromProto(proto, FromProtoOptions{});
    }

    absl::StatusOr<std::unique_ptr<cppbor::Map>> FromProto(
        const $name$& proto, FromProtoOptions options) {
      auto map = std::make_unique<cppbor::Map>();
  )cc");
  {
    auto indent = printer.WithIndent();
    for (int i = 0; i < desc->field_count(); ++i) {
      const auto* field = desc->field(i);
      const auto& tags = GetTags(field);

      if (tags.mode() == cbor::Tags::MODE_READ_ONLY ||
          tags.mode() == cbor::Tags::MODE_SKIP) {
        continue;
      }

      std::string key = GetCborKey(field);
      if (field->is_repeated()) {
        if (tags.is_required() && tags.disallow_empty()) {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            if (!options.skip_validation && proto.$field$_size() == 0) {
              return absl::InvalidArgumentError("Field $key$ cannot be empty");
            }
          )cc");
        }
        if (tags.is_required()) {
          printer.Emit(R"cc(
            {
          )cc");
        } else {
          printer.Emit({{"field", field->name()}}, R"cc(
            if (proto.$field$_size() > 0) {
          )cc");
        }

        if (field->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            auto array = std::make_unique<cppbor::Array>();
            for (int i = 0; i < proto.$field$_size(); ++i) {
              ABSL_ASSIGN_OR_RETURN(auto item, FromProto(proto.$field$(i)));
              array->add(std::move(item));
            }
            map->add("$key$", std::move(array));
          )cc");
        } else if (field->type() ==
                   google::protobuf::FieldDescriptor::TYPE_BYTES) {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            auto array = std::make_unique<cppbor::Array>();
            for (int i = 0; i < proto.$field$_size(); ++i) {
              array->add(cppbor::Bstr(std::string(proto.$field$(i))));
            }
            map->add("$key$", std::move(array));
          )cc");
        } else if (field->type() ==
                   google::protobuf::FieldDescriptor::TYPE_STRING) {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            auto array = std::make_unique<cppbor::Array>();
            for (int i = 0; i < proto.$field$_size(); ++i) {
              array->add(cppbor::Tstr(std::string(proto.$field$(i))));
            }
            map->add("$key$", std::move(array));
          )cc");
        } else if (field->type() ==
                   google::protobuf::FieldDescriptor::TYPE_FLOAT) {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            auto array = std::make_unique<cppbor::Array>();
            for (int i = 0; i < proto.$field$_size(); ++i) {
              array->add(cppbor::Float(proto.$field$(i)));
            }
            map->add("$key$", std::move(array));
          )cc");
        } else if (field->type() ==
                   google::protobuf::FieldDescriptor::TYPE_DOUBLE) {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            auto array = std::make_unique<cppbor::Array>();
            for (int i = 0; i < proto.$field$_size(); ++i) {
              array->add(cppbor::Double(proto.$field$(i)));
            }
            map->add("$key$", std::move(array));
          )cc");
        } else {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            auto array = std::make_unique<cppbor::Array>();
            for (int i = 0; i < proto.$field$_size(); ++i) {
              array->add(proto.$field$(i));
            }
            map->add("$key$", std::move(array));
          )cc");
        }

        printer.Emit(R"cc(
          }
        )cc");
      } else {
        if (tags.is_required()) {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            if (!options.skip_validation && !proto.has_$field$()) {
              return absl::InvalidArgumentError(
                  "Missing required field: "
                  "$key$");
            }
          )cc");
        }
        if (field->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            if (proto.has_$field$()) {
              ABSL_ASSIGN_OR_RETURN(auto item, FromProto(proto.$field$()));
              map->add("$key$", std::move(item));
            }
          )cc");
        } else if (field->type() ==
                   google::protobuf::FieldDescriptor::TYPE_BYTES) {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            if (proto.has_$field$()) {
              map->add("$key$", cppbor::Bstr(std::string(proto.$field$())));
            }
          )cc");
        } else if (field->type() ==
                   google::protobuf::FieldDescriptor::TYPE_STRING) {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            if (proto.has_$field$()) {
              map->add("$key$", cppbor::Tstr(std::string(proto.$field$())));
            }
          )cc");
        } else if (field->type() ==
                   google::protobuf::FieldDescriptor::TYPE_FLOAT) {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            if (proto.has_$field$()) {
              map->add("$key$", cppbor::Float(proto.$field$()));
            }
          )cc");
        } else if (field->type() ==
                   google::protobuf::FieldDescriptor::TYPE_DOUBLE) {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            if (proto.has_$field$()) {
              map->add("$key$", cppbor::Double(proto.$field$()));
            }
          )cc");
        } else {
          printer.Emit({{"field", field->name()}, {"key", key}}, R"cc(
            if (proto.has_$field$()) {
              map->add("$key$", proto.$field$());
            }
          )cc");
        }
      }
    }
    printer.Emit(R"cc(
      return map;
    )cc");
  }
  printer.Emit(R"cc(
    }
  )cc");
  for (int i = 0; i < desc->nested_type_count(); ++i) {
    GenerateFromProtoBody(desc->nested_type(i), printer);
  }
}

void CollectUsedDeps(
    const google::protobuf::Descriptor* descriptor,
    const google::protobuf::FileDescriptor* current_file,
    absl::flat_hash_set<const google::protobuf::FileDescriptor*>& used_deps) {
  for (int i = 0; i < descriptor->field_count(); ++i) {
    const auto* f = descriptor->field(i);
    if (f->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
      if (GetTags(f).mode() == cbor::Tags::MODE_SKIP) {
        continue;
      }
      const auto* m = f->message_type();
      if (m->file() != current_file) {
        used_deps.insert(m->file());
      }
    }
  }
  for (int i = 0; i < descriptor->nested_type_count(); ++i) {
    CollectUsedDeps(descriptor->nested_type(i), current_file, used_deps);
  }
}

void GenerateHeader(const google::protobuf::FileDescriptor* file,
                    absl::string_view base_name,
                    google::protobuf::compiler::GeneratorContext* context) {
  std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> h_stream(
      context->Open(absl::StrCat(base_name, ".cbor.h")));
  google::protobuf::io::Printer h_printer(h_stream.get());

  std::string guard = absl::AsciiStrToUpper(absl::StrReplaceAll(
      absl::StrCat(base_name, "_CBOR_H_"), {{"/", "_"}, {".", "_"}}));
  h_printer.Emit({{"guard", guard}}, R"cc(
#ifndef $guard$
#define $guard$
  )cc");

  if (file->message_type_count() > 0) {
    h_printer.Emit(R"cc(
#include <memory>

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "cbor/cbor.h"
#include "cbor/options.h"
#include "cppbor/cppbor.h"
    )cc");
  }

  h_printer.Emit({{"base", base_name}}, R"cc(
#include "$base$.pb.h"
  )cc");

  for (int i = 0; i < file->public_dependency_count(); ++i) {
    absl::string_view pub_base =
        StripProtoExtension(file->public_dependency(i)->name());
    h_printer.Emit({{"pub", pub_base}}, R"cc(
#include "$pub$.cbor.h"  // IWYU pragma: export
    )cc");
  }

  h_printer.Emit(R"cc(
    namespace cbor {
  )cc");

  for (int i = 0; i < file->message_type_count(); ++i) {
    GenerateMessageHeader(file->message_type(i), h_printer);
  }

  h_printer.Emit({{"guard", guard}}, R"cc(
    }  // namespace cbor

#endif  // $guard$
  )cc");
}

void GenerateCc(const google::protobuf::FileDescriptor* file,
                absl::string_view base_name,
                google::protobuf::compiler::GeneratorContext* context) {
  std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> cc_stream(
      context->Open(absl::StrCat(base_name, ".cbor.cc")));
  google::protobuf::io::Printer cc_printer(cc_stream.get());

  cc_printer.Emit({{"base", base_name}}, R"cc(
#include "$base$.cbor.h"
  )cc");

  if (file->message_type_count() > 0) {
    cc_printer.Emit({{"base", base_name}}, R"cc(
#include "$base$.pb.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "cbor/cbor.h"
#include "cppbor/cppbor.h"
    )cc");
  }

  absl::flat_hash_set<const google::protobuf::FileDescriptor*> used_deps;
  for (int i = 0; i < file->message_type_count(); ++i) {
    CollectUsedDeps(file->message_type(i), file, used_deps);
  }

  for (const auto* dep : used_deps) {
    absl::string_view dep_base = StripProtoExtension(dep->name());
    cc_printer.Emit({{"dep", dep_base}}, R"cc(
#include "$dep$.cbor.h"
    )cc");
  }

  cc_printer.Emit(R"cc(
    namespace cbor {
  )cc");

  for (int i = 0; i < file->message_type_count(); ++i) {
    GenerateToProtoBody(file->message_type(i), cc_printer);
    GenerateFromProtoBody(file->message_type(i), cc_printer);
  }

  cc_printer.Emit(R"cc(
    }  // namespace cbor
  )cc");
}

}  // namespace

bool CborGenerator::Generate(
    const google::protobuf::FileDescriptor* file, const std::string& parameter,
    google::protobuf::compiler::GeneratorContext* context,
    std::string* error) const {
  absl::string_view base_name = StripProtoExtension(file->name());

  GenerateHeader(file, base_name, context);
  GenerateCc(file, base_name, context);

  return true;
}

}  // namespace cbor
