# Copyright 2025 The Bazel Authors. All rights reserved.
#
# 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
#
#    http://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.

"""Common util functions for java_* rules"""

load("@bazel_skylib//lib:paths.bzl", "paths")
load("//java/common:java_semantics.bzl", "semantics")

# copybara: rules_java visibility

def _java_segments(path):
    if path.startswith("/"):
        fail("path must not be absolute: '%s'" % path)
    if path.startswith("third_party/java/"):
        # For third_party/java, try skipping past the first two segments and looking for a nested
        # source root, to relativize e.g. third_party/java/foo/java/resource into 'resource',
        # not 'foo/java/resource'.
        segments = _java_segments_impl(path[len("third_party/java/"):])
        if segments != None:
            return segments
    return _java_segments_impl(path)

def _java_segments_impl(path):
    segments = path.split("/")
    root_idx = -1
    for idx, segment in enumerate(segments):
        if segment in ["java", "javatests", "src", "testsrc"]:
            root_idx = idx
            break
    if root_idx < 0:
        return None
    is_src = "src" == segments[root_idx]
    check_mvn_idx = root_idx if is_src else -1
    if (root_idx == 0 or is_src):
        for i in range(root_idx + 1, len(segments) - 1):
            segment = segments[i]
            if "src" == segment or (is_src and (segment in ["java", "javatests"])):
                next = segments[i + 1]
                if next in ["com", "org", "net"]:
                    root_idx = i
                elif "src" == segment:
                    check_mvn_idx = i
                break

    if check_mvn_idx >= 0 and check_mvn_idx < len(segments) - 2:
        next = segments[check_mvn_idx + 1]
        if next in ["main", "test"]:
            next = segments[check_mvn_idx + 2]
            if next in ["java", "resources"]:
                root_idx = check_mvn_idx + 2
    return segments[(root_idx + 1):]

def _has_target_constraints(ctx, constraints):
    # Constraints is a label_list.
    for constraint in constraints:
        constraint_value = constraint[platform_common.ConstraintValueInfo]
        if ctx.target_platform_has_constraint(constraint_value):
            return True
    return False

def _is_target_platform_windows(ctx):
    return _has_target_constraints(ctx, ctx.attr._windows_constraints)

def _resource_mapper(file):
    root_relative_path = paths.relativize(
        path = file.path,
        start = paths.join(file.root.path, file.owner.workspace_root),
    )
    return "%s:%s" % (
        file.path,
        semantics.get_default_resource_path(root_relative_path, segment_extractor = _java_segments),
    )

def _create_single_jar(
        actions,
        toolchain,
        output,
        sources = depset(),
        resources = depset(),
        mnemonic = "JavaSingleJar",
        progress_message = "Building singlejar jar %{output}",
        build_target = None,
        output_creator = None):
    """Register singlejar action for the output jar.

    Args:
      actions: (actions) ctx.actions
      toolchain: (JavaToolchainInfo) The java toolchain
      output: (File) Output file of the action.
      sources: (depset[File]) The jar files to merge into the output jar.
      resources: (depset[File]) The files to add to the output jar.
      mnemonic: (str) The action identifier
      progress_message: (str) The action progress message
      build_target: (Label) The target label to stamp in the manifest. Optional.
      output_creator: (str) The name of the tool to stamp in the manifest. Optional,
          defaults to 'singlejar'
    Returns:
      (File) Output file which was used for registering the action.
    """
    args = actions.args()
    args.set_param_file_format("shell").use_param_file("@%s", use_always = True)
    args.add("--output", output)
    args.add_all(
        [
            "--compression",
            "--normalize",
            "--exclude_build_data",
            "--warn_duplicate_resources",
        ],
    )
    args.add_all("--sources", sources)
    args.add_all("--resources", resources, map_each = _resource_mapper)

    args.add("--build_target", build_target)
    args.add("--output_jar_creator", output_creator)

    actions.run(
        mnemonic = mnemonic,
        progress_message = progress_message,
        executable = toolchain.single_jar,
        toolchain = semantics.JAVA_TOOLCHAIN_TYPE,
        inputs = depset(transitive = [resources, sources]),
        tools = [toolchain.single_jar],
        outputs = [output],
        arguments = [args],
        use_default_shell_env = True,
    )
    return output

# TODO(hvd): use skylib shell.quote()
def _shell_escape(s):
    """Shell-escape a string

    Quotes a word so that it can be used, without further quoting, as an argument
    (or part of an argument) in a shell command.

    Args:
        s: (str) the string to escape

    Returns:
        (str) the shell-escaped string
    """
    if not s:
        # Empty string is a special case: needs to be quoted to ensure that it
        # gets treated as a separate argument.
        return "''"
    for c in s.elems():
        # We do this positively so as to be sure we don't inadvertently forget
        # any unsafe characters.
        if not c.isalnum() and c not in "@%-_+:,./":
            return "'" + s.replace("'", "'\\''") + "'"
    return s

def _detokenize_javacopts(opts):
    """Detokenizes a list of options to a depset.

    Args:
        opts: ([str]) the javac options to detokenize

    Returns:
        (depset[str]) depset of detokenized options
    """
    return depset(
        [" ".join([_shell_escape(opt) for opt in opts])],
        order = "preorder",
    )

def _get_relative(path_a, path_b):
    if paths.is_absolute(path_b):
        return path_b
    return paths.normalize(paths.join(path_a, path_b))

def _tokenize_javacopts(ctx = None, opts = []):
    """Tokenizes a list or depset of options to a list.

    Iff opts is a depset, we reverse the flattened list to ensure right-most
    duplicates are preserved in their correct position.

    If the ctx parameter is omitted, a slow, but pure Starlark, implementation
    of shell tokenization is used. Otherwise, tokenization is performed using
    ctx.tokenize() which has significantly better performance (up to 100x for
    large options lists).

    Args:
        ctx: (RuleContext|None) the rule context
        opts: (depset[str]|[str]) the javac options to tokenize
    Returns:
        [str] list of tokenized options
    """
    if hasattr(opts, "to_list"):
        opts = reversed(opts.to_list())
    if ctx:
        return [
            token
            for opt in opts
            for token in ctx.tokenize(opt)
        ]
    else:
        # TODO: optimize and use the pure Starlark implementation in cc_helper
        return semantics.tokenize_javacopts(opts)

helper = struct(
    is_target_platform_windows = _is_target_platform_windows,
    create_single_jar = _create_single_jar,
    shell_escape = _shell_escape,
    detokenize_javacopts = _detokenize_javacopts,
    tokenize_javacopts = _tokenize_javacopts,
    get_relative = _get_relative,
    has_target_constraints = _has_target_constraints,
    java_segments = _java_segments,
)
