"""A custom @rules_testing subject for the JavaInfo provider"""

load("@rules_testing//lib:truth.bzl", "subjects", "truth")
load("//java/common:java_common.bzl", "java_common")
load("//java/common:java_info.bzl", "JavaInfo")
load("//java/common:java_plugin_info.bzl", "JavaPluginInfo")
load("//java/common/rules/impl:java_helper.bzl", "helper")
load(":cc_info_subject.bzl", "cc_info_subject")

def _new_java_info_subject(java_info, meta):
    self = struct(actual = java_info, meta = meta.derive("JavaInfo"))
    public = struct(
        compilation_args = lambda: _new_java_compilation_args_subject(self.actual, self.meta),
        compilation_info = lambda: _new_java_compilation_info_subject(self.actual, self.meta),
        plugins = lambda: _new_java_plugin_data_subject(self.actual.plugins, self.meta.derive("plugins")),
        api_generating_plugins = lambda: _new_java_plugin_data_subject(self.actual.api_generating_plugins, self.meta.derive("api_generating_plugins")),
        is_binary = lambda: subjects.bool(getattr(java_info, "_is_binary", False), self.meta.derive("_is_binary")),
        has_attr = lambda a: subjects.bool(getattr(java_info, a, None) != None, meta = self.meta.derive("{} != None".format(a))).equals(True),
        cc_link_params_info = lambda: cc_info_subject.new_from_java_info(java_info, meta),
        transitive_native_libraries = lambda: cc_info_subject.libraries_to_link(java_info.transitive_native_libraries, self.meta.derive("transitive_native_libraries")),
        constraints = lambda: subjects.collection(java_common.get_constraints(java_info), self.meta.derive("constraints")),
        annotation_processing = lambda: _new_annotation_processing_subject(self.actual, self.meta),
        outputs = lambda: _new_rule_output_info_subject(self.actual, self.meta),
        java_outputs = lambda: _new_java_outputs_collection_subject(self.actual.java_outputs, self.meta.derive("java_outputs")),
        source_jars = lambda: subjects.collection(java_info.source_jars, self.meta.derive("source_jars")),
        transitive_source_jars = lambda: subjects.depset_file(java_info.transitive_source_jars, self.meta.derive("transitive_source_jars")),
        transitive_source_jars_list = lambda: subjects.collection(java_info.transitive_source_jars.to_list(), self.meta.derive("transitive_source_jars.to_list()")),
        runtime_output_jars = lambda: subjects.depset_file(java_info.runtime_output_jars, self.meta.derive("runtime_output_jars")),
        module_flags = lambda: _new_java_module_flags_subject(self.actual, self.meta),
    )
    return public

def _java_info_subject_from_target(env, target):
    return _new_java_info_subject(target[JavaInfo], meta = truth.expect(env).meta.derive(
        format_str_kwargs = {
            "name": target.label.name,
            "package": target.label.package,
        },
    ))

def _new_java_module_flags_subject(java_info, meta):
    self = struct(
        actual = java_info.module_flags_info,
        meta = meta.derive("module_flags_info"),
    )
    public = struct(
        add_exports = lambda: subjects.collection(self.actual.add_exports.to_list(), self.meta.derive("add_exports")),
        add_opens = lambda: subjects.collection(self.actual.add_opens.to_list(), self.meta.derive("add_opens")),
    )
    return public

def _new_java_compilation_info_subject(java_info, meta):
    self = struct(
        actual = java_info.compilation_info,
        meta = meta.derive("compilation_info"),
    )
    public = struct(
        compilation_classpath = lambda: subjects.depset_file(self.actual.compilation_classpath, self.meta.derive("compilation_classpath")),
        runtime_classpath = lambda: subjects.depset_file(self.actual.runtime_classpath, self.meta.derive("runtime_classpath")),
        runtime_classpath_list = lambda: subjects.collection(self.actual.runtime_classpath.to_list(), self.meta.derive("runtime_classpath.to_list()"), format = True),
        javac_options = lambda: subjects.collection(helper.tokenize_javacopts(opts = self.actual.javac_options), self.meta.derive("javac_options")),
    )
    return public

def _new_rule_output_info_subject(java_info, meta):
    actual = java_info.outputs
    self = struct(
        actual = actual,
        meta = meta.derive("outputs"),
    )

    # JavaOutputInfo.source_jars is a list before Bazel 7
    source_jars_depset = depset([f for o in actual.jars for f in (o.source_jars.to_list() if hasattr(o.source_jars, "to_list") else o.source_jars)])
    public = struct(
        jars = lambda: _new_java_outputs_collection_subject(actual.jars, self.meta.derive("jars")),
        class_output_jars = lambda: subjects.depset_file(depset([o.class_jar for o in actual.jars]), self.meta.derive("class_output_jars")),
        source_output_jars = lambda: subjects.depset_file(source_jars_depset, self.meta.derive("source_output_jars")),
        generated_class_jars = lambda: subjects.depset_file(depset([o.generated_class_jar for o in actual.jars]), self.meta.derive("generated_class_jars")),
        generated_source_jars = lambda: subjects.depset_file(depset([o.generated_source_jar for o in actual.jars]), self.meta.derive("generated_source_jars")),
        jdeps = lambda: subjects.depset_file(depset([o.jdeps for o in actual.jars]), self.meta.derive("jdeps")),
        compile_jdeps = lambda: subjects.depset_file(depset([o.compile_jdeps for o in actual.jars]), self.meta.derive("compile_jdeps")),
        native_headers = lambda: subjects.depset_file(depset([o.native_headers_jar for o in actual.jars]), self.meta.derive("native_headers")),
        manifest_protos = lambda: subjects.depset_file(depset([o.manifest_proto for o in actual.jars]), self.meta.derive("manifest_protos")),
    )
    return public

def _new_java_outputs_collection_subject(java_outputs, meta):
    public = struct(
        singleton = lambda: _new_java_outputs_subject(_get_singleton(java_outputs), meta.derive("[0]")),
    )
    return public

def _new_java_outputs_subject(java_output, meta):
    public = struct(
        class_jar = lambda: subjects.file(java_output.class_jar, meta.derive("class_jar")),
        compile_jar = lambda: subjects.file(java_output.compile_jar, meta.derive("compile_jar")),
        source_jars = lambda: subjects.depset_file(java_output.source_jars if hasattr(java_output.source_jars, "to_list") else depset(java_output.source_jars), meta.derive("source_jars")),
        jdeps = lambda: subjects.file(java_output.jdeps, meta.derive("jdeps")),
        compile_jdeps = lambda: subjects.file(java_output.compile_jdeps, meta.derive("compile_jdeps")),
        native_headers_jar = lambda: subjects.file(java_output.native_headers_jar, meta.derive("native_headers_jar")),
    )
    return public

def _new_java_compilation_args_subject(java_info, meta):
    is_binary = getattr(java_info, "_is_binary", False)
    actual = struct(
        transitive_runtime_jars = java_info.transitive_runtime_jars,
        compile_jars = java_info.compile_jars,
        transitive_compile_time_jars = java_info.transitive_compile_time_jars,
        full_compile_jars = java_info.full_compile_jars,
        _transitive_full_compile_time_jars = getattr(java_info, "_transitive_full_compile_time_jars", None),  # not in Bazel 6
        _compile_time_java_dependencies = getattr(java_info, "_compile_time_java_dependencies", None),  # not in Bazel 6
    ) if not is_binary else None
    self = struct(
        actual = actual,
        meta = meta,
    )
    return struct(
        equals = lambda other: _java_compilation_args_equals(self, other),
        equals_subject = lambda other: _java_compilation_args_equals(self, other.actual),
        compile_jars = lambda: subjects.depset_file(actual.compile_jars, self.meta.derive("compile_jars")),
        full_compile_jars = lambda: subjects.depset_file(actual.full_compile_jars, self.meta.derive("full_compile_jars")),
        transitive_runtime_jars = lambda: subjects.depset_file(actual.transitive_runtime_jars, self.meta.derive("transitive_runtime_jars")),
        transitive_compile_time_jars = lambda: subjects.depset_file(actual.transitive_compile_time_jars, self.meta.derive("transitive_compile_time_jars")),
        transitive_runtime_jars_list = lambda: subjects.collection(actual.transitive_runtime_jars.to_list(), self.meta.derive("transitive_runtime_jars.to_list()")),
        compile_time_java_dependencies = lambda: subjects.depset_file(actual._compile_time_java_dependencies, self.meta.derive("_compile_time_java_dependencies")),
        self = self,
        actual = actual,
    )

def _java_compilation_args_equals(self, other):
    if self.actual == other:
        return
    for attr in dir(other):
        other_attr = getattr(other, attr)
        this_attr = getattr(self.actual, attr)
        if this_attr != other_attr:
            self.meta.derive(attr).add_failure(
                "expected: {}".format(other_attr),
                "actual: {}".format(this_attr),
            )

def _new_java_plugin_data_subject(java_plugin_data, meta):
    public = struct(
        processor_jars = lambda: subjects.depset_file(java_plugin_data.processor_jars, meta = meta.derive("processor_jars")),
        processor_classes = lambda: subjects.collection(java_plugin_data.processor_classes, meta = meta.derive("processor_classes")),
        processor_data = lambda: subjects.depset_file(java_plugin_data.processor_data, meta = meta.derive("processor_data")),
        is_empty = lambda: _check_plugin_data_empty(java_plugin_data, meta.derive("is_empty()")),
        equals = lambda other: subjects.bool(java_plugin_data == other, meta.derive("equals({})".format(other))).equals(True),
    )
    return public

def _check_plugin_data_empty(plugin_data, meta):
    for attr in ["processor_jars", "processor_classes", "processor_data"]:
        value = getattr(plugin_data, attr)
        if value:
            meta.add_failure(
                "expected: {} to be empty".format(attr),
                "actual: {}".format(value),
            )

def _new_annotation_processing_subject(java_info, meta):
    actual = java_info.annotation_processing
    meta = meta.derive("annotation_processing")
    self = struct(
        actual = actual,
        meta = meta,
    )
    public = struct(
        is_enabled = lambda: subjects.bool(actual.enabled, meta = meta.derive("is_enabled")),
        processor_classnames = lambda: subjects.collection(actual.processor_classnames, meta = meta.derive("processor_classnames")),
        processor_classpath = lambda: subjects.depset_file(actual.processor_classpath, meta = meta.derive("processor_classpath")),
        class_jar = lambda: subjects.file(actual.class_jar, meta = meta.derive("class_jar")),
        source_jar = lambda: subjects.file(actual.source_jar, meta = meta.derive("source_jar")),
        transitive_class_jars = lambda: subjects.depset_file(actual.transitive_class_jars, meta = meta.derive("transitive_class_jars")),
        transitive_source_jars = lambda: subjects.depset_file(actual.transitive_source_jars, meta = meta.derive("transitive_source_jars")),
        actual = actual,
        self = self,
    )
    return public

def _new_java_plugin_info_subject(java_plugin_info, meta):
    self = struct(actual = java_plugin_info, meta = meta.derive("JavaPluginInfo"))
    public = struct(
        java_outputs = lambda: _new_java_outputs_collection_subject(self.actual.java_outputs, self.meta.derive("java_outputs")),
        plugins = lambda: _new_java_plugin_data_subject(self.actual.plugins, self.meta.derive("plugins")),
        api_generating_plugins = lambda: _new_java_plugin_data_subject(self.actual.api_generating_plugins, self.meta.derive("api_generating_plugins")),
    )
    return public

def _java_plugin_info_subject_from_target(env, target):
    return _new_java_plugin_info_subject(target[JavaPluginInfo], meta = truth.expect(env).meta.derive(
        format_str_kwargs = {
            "name": target.label.name,
            "package": target.label.package,
        },
    ))

def _get_singleton(seq):
    if len(seq) != 1:
        fail("expected singleton, got:", seq)
    return seq[0]

java_info_subject = struct(
    new = _new_java_info_subject,
    from_target = _java_info_subject_from_target,
)

java_plugin_info_subject = struct(
    new = _new_java_plugin_info_subject,
    from_target = _java_plugin_info_subject_from_target,
)
