load("@rules_cc//cc:defs.bzl", "objc_library")
load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix")
load("//conformance:defs.bzl", "conformance_test")
load("//upb/cmake:build_defs.bzl", "staleness_test")
load(":defs.bzl", "objc_proto_camel_case_name")

# The WKTs have to be checked in to support the CocoaPods and Xcode builds. This
# generule and test ensure the source are current.
#
# TODO: Improve the bazel build so it uses these generated headers so it is
# always current, and only the builds that can't easily build protoc and
# generate the files rely on the checked in ones.

_WELL_KNOWN_TYPES = [
    "any",
    "api",
    "duration",
    "empty",
    "field_mask",
    "source_context",
    "struct",
    "timestamp",
    "type",
    "wrappers",
]

_OBJC_WKT_NAMES = [objc_proto_camel_case_name(x) for x in _WELL_KNOWN_TYPES]

_OBJC_EXTS = [
    ".pbobjc.h",
    ".pbobjc.m",
]

genrule(
    name = "gen_wkt_sources",
    srcs = ["//src/google/protobuf:well_known_type_protos"],
    outs = ["wkt/GPB" + wkt + ext for wkt in _OBJC_WKT_NAMES for ext in _OBJC_EXTS],
    cmd = " && ".join([
        "$(execpath //:protoc) --objc_out=$(RULEDIR)/wkt --proto_path=src $(SRCS)",
    ] + [
        "mv $(RULEDIR)/wkt/google/protobuf/" + wkt + ext + " $(RULEDIR)/wkt/GPB" + wkt + ext
        for wkt in _OBJC_WKT_NAMES
        for ext in _OBJC_EXTS
    ]),
    tags = ["manual"],
    tools = ["//:protoc"],
)

staleness_test(
    name = "well_known_types_staleness_test",
    outs = ["GPB" + wkt + ext for wkt in _OBJC_WKT_NAMES for ext in _OBJC_EXTS],
    generated_pattern = "wkt/%s",
    tags = ["manual"],
)

################################################################################
# Objective-C Runtime Library
################################################################################

objc_library(
    name = "objectivec",
    srcs = [
        # Private headers that aren't used from the generated sources.
        "GPBUnknownFields_PackagePrivate.h",
    ],
    hdrs = [
        "GPBAny.pbobjc.h",
        "GPBApi.pbobjc.h",
        "GPBDuration.pbobjc.h",
        "GPBEmpty.pbobjc.h",
        "GPBFieldMask.pbobjc.h",
        "GPBSourceContext.pbobjc.h",
        "GPBStruct.pbobjc.h",
        "GPBTimestamp.pbobjc.h",
        "GPBType.pbobjc.h",
        "GPBWrappers.pbobjc.h",
        "GPBArray.h",
        "GPBBootstrap.h",
        "GPBCodedInputStream.h",
        "GPBCodedOutputStream.h",
        "GPBDescriptor.h",
        "GPBDictionary.h",
        "GPBExtensionInternals.h",
        "GPBExtensionRegistry.h",
        "GPBMessage.h",
        "GPBProtocolBuffers.h",
        "GPBProtocolBuffers_RuntimeSupport.h",
        "GPBRootObject.h",
        "GPBRuntimeTypes.h",
        "GPBUnknownField.h",
        "GPBUnknownFields.h",
        "GPBUnknownFieldSet.h",
        "GPBUtilities.h",
        "GPBWellKnownTypes.h",
        "GPBWireFormat.h",
        "google/protobuf/Any.pbobjc.h",
        "google/protobuf/Api.pbobjc.h",
        "google/protobuf/Duration.pbobjc.h",
        "google/protobuf/Empty.pbobjc.h",
        "google/protobuf/FieldMask.pbobjc.h",
        "google/protobuf/SourceContext.pbobjc.h",
        "google/protobuf/Struct.pbobjc.h",
        "google/protobuf/Timestamp.pbobjc.h",
        "google/protobuf/Type.pbobjc.h",
        "google/protobuf/Wrappers.pbobjc.h",
        # Package private headers, but exposed because the generated sources
        # need to use them.
        "GPBArray_PackagePrivate.h",
        "GPBCodedInputStream_PackagePrivate.h",
        "GPBCodedOutputStream_PackagePrivate.h",
        "GPBDescriptor_PackagePrivate.h",
        "GPBDictionary_PackagePrivate.h",
        "GPBMessage_PackagePrivate.h",
        "GPBRootObject_PackagePrivate.h",
        "GPBUnknownFieldSet_PackagePrivate.h",
        "GPBUnknownField_PackagePrivate.h",
        "GPBUtilities_PackagePrivate.h",
    ],
    copts = [
        "-Wno-vla",
    ],
    includes = [
        ".",
    ],
    non_arc_srcs = [
        "GPBAny.pbobjc.m",
        "GPBApi.pbobjc.m",
        "GPBArray.m",
        "GPBCodedInputStream.m",
        "GPBCodedOutputStream.m",
        "GPBDescriptor.m",
        "GPBDictionary.m",
        "GPBDuration.pbobjc.m",
        "GPBEmpty.pbobjc.m",
        "GPBExtensionInternals.m",
        "GPBExtensionRegistry.m",
        "GPBFieldMask.pbobjc.m",
        "GPBMessage.m",
        "GPBRootObject.m",
        "GPBSourceContext.pbobjc.m",
        "GPBStruct.pbobjc.m",
        "GPBTimestamp.pbobjc.m",
        "GPBType.pbobjc.m",
        "GPBUnknownField.m",
        "GPBUnknownFieldSet.m",
        "GPBUnknownFields.m",
        "GPBUtilities.m",
        "GPBWellKnownTypes.m",
        "GPBWireFormat.m",
        "GPBWrappers.pbobjc.m",
    ],
    target_compatible_with = select({
        "@platforms//os:macos": [],
        "@platforms//os:ios": [],
        "@platforms//os:tvos": [],
        "@platforms//os:watchos": [],
        "//conditions:default": ["@platforms//:incompatible"],
    }),
    visibility = ["//visibility:public"],
)

################################################################################
# Tests
################################################################################

conformance_test(
    name = "conformance_test",
    failure_list = "//conformance:failure_list_objc.txt",
    maximum_edition = "2023",
    target_compatible_with = ["@platforms//os:macos"],
    testee = "//conformance:conformance_objc",
)

# -------------------------------------------------------------------
# Current Version Check between Generator and Runtime Sources
sh_test(
    name = "check_version_stamps",
    size = "small",
    srcs = ["DevTools/check_version_stamps.sh"],
    data = [
        "GPBBootstrap.h",
        "//src/google/protobuf/compiler/objectivec:file.cc",
    ],
)

# -------------------------------------------------------------------
# Validation of pddm expansion.

py_binary(
    name = "pddm",
    srcs = ["DevTools/pddm.py"],
)

py_test(
    name = "pddm_tests",
    size = "small",
    srcs = [
        "DevTools/pddm.py",
        "DevTools/pddm_tests.py",
    ],
)

sh_test(
    name = "sources_pddm_expansion_test",
    size = "small",
    srcs = ["DevTools/sources_pddm_expansion_test.sh"],
    data = [":pddm"] + glob([
        "**/*.h",
        "**/*.m",
        "**/*.pddm",
    ]),
)

################################################################################
# Distribution files
################################################################################

pkg_files(
    name = "dist_files",
    srcs = glob([
        "*.h",
        "*.m",
        "**/*.h",
        "**/*.m",
        "**/*.mm",
        "**/*.swift",
        "DevTools/*.sh",
        "DevTools/*.py",
        "ProtocolBuffers_iOS.xcodeproj/**/*",
        "ProtocolBuffers_OSX.xcodeproj/**/*",
        "ProtocolBuffers_tvOS.xcodeproj/**/*",
        "Tests/*.pddm",
        "Tests/*.txt",
        "Tests/*.plist",
        "Tests/*.proto",
    ]) + [
        ".clang-format",
        "BUILD.bazel",
        "README.md",
        "Tests/golden_message",
        "Tests/golden_packed_fields_message",
        "generate_well_known_types.sh",
    ],
    strip_prefix = strip_prefix.from_root(""),
    visibility = ["//pkg:__pkg__"],
)
