# Copyright 2020 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 implementation for processing pipelines."""

load("//rules:visibility.bzl", "PROJECT_VISIBILITY")

visibility(PROJECT_VISIBILITY)
PROVIDERS = "providers"
VALIDATION_OUTPUTS = "validation_outputs"
IMPLICIT_OUTPUTS = "implicit_outputs"
OUTPUT_GROUPS = "output_groups"

# TODO(djwhang): When a provider type can be retrieved from a Starlark provider
# ProviderInfo is necessary. Once this is possible, processor methods can have a
# uniform method signature foo(ctx, target_ctx) where we can pull the provider
# off the target_ctx using the provider type.
#
# Yes, this effectively leads to producing a build rule like system within a
# build rule, rather than resorting to rule based composition.
ProviderInfo = provider(
    "Stores metadata about the actual Starlark provider returned.",
    fields = dict(
        name = "The type of the provider",
        value = "The actual provider",
        runfiles = "Runfiles to pass to the DefaultInfo provider",
    ),
)

_ProcessingPipelineInfo = provider(
    "Stores functions that forms a rule's implementation.",
    fields = dict(
        processors = "Ordered dictionary of processing functions.",
        finalize = "Function to form the final providers to propagate.",
    ),
)

def _make_processing_pipeline(processors = dict(), finalize = None):
    """Creates the combined processing pipeline.

    Args:
      processors: Ordered dictionary of processing functions.
      finalize: Function to form the final providers to propagate.

    Returns:
      A _ProcessingPipelineInfo provider.
    """
    return _ProcessingPipelineInfo(
        processors = processors,
        finalize = finalize,
    )

def _run(ctx, java_package, processing_pipeline):
    """Runs the processing pipeline and populates the target context.

    Args:
      ctx: The context.
      java_package: The java package resolved from the target's path
        or the custom_package attr.
      processing_pipeline: The _ProcessingPipelineInfo provider for this target.

    Returns:
      The output of the _ProcessingPipelineInfo.finalize function.
    """
    target_ctx = dict(
        java_package = java_package,
        providers = [],
        validation_outputs = [],
        implicit_outputs = [],
        output_groups = {},
        runfiles = ctx.runfiles(),
    )

    for execute in processing_pipeline.processors.values():
        info = execute(ctx, **target_ctx)
        if info:
            if info.name in target_ctx:
                fail("%s provider already registered in target context" % info.name)
            target_ctx[info.name] = info.value
            target_ctx[PROVIDERS].extend(getattr(info.value, PROVIDERS, []))
            target_ctx[VALIDATION_OUTPUTS].extend(getattr(info.value, VALIDATION_OUTPUTS, []))
            target_ctx[IMPLICIT_OUTPUTS].extend(getattr(info.value, IMPLICIT_OUTPUTS, []))

            output_groups = getattr(info.value, OUTPUT_GROUPS, {})
            for key, value in output_groups.items():
                if key == "_validation":
                    fail("Do not explicitly set '_validation' as an output group. Use 'validation_outputs' instead.")
                if key == "_hidden_top_level_INTERNAL_":
                    fail("Do not set '_hidden_top_level_INTERNAL_' in processors as an output group. Set it instead in the finalize method.")
                if key in target_ctx[OUTPUT_GROUPS]:
                    fail("%s output group already registered in target context" % key)
                target_ctx[OUTPUT_GROUPS][key] = value

            if hasattr(info, "runfiles") and info.runfiles:
                target_ctx["runfiles"] = target_ctx["runfiles"].merge(info.runfiles)

    return processing_pipeline.finalize(ctx, **target_ctx)

def _prepend(processors, **new_processors):
    """Prepends processors in a given processing pipeline.

    Args:
      processors: The dictionary representing the processing pipeline.
      **new_processors: The processors to add where the key represents the
        name of the processor and value is the function pointer to the new
        processor.

    Returns:
      A dictionary which represents the new processing pipeline.
    """
    updated_processors = dict()
    for name, processor in new_processors.items():
        updated_processors[name] = processor

    for key in processors.keys():
        updated_processors[key] = processors[key]

    return updated_processors

def _append(processors, **new_processors):
    """Appends processors in a given processing pipeline.

    Args:
      processors: The dictionary representing the processing pipeline.
      **new_processors: The processors to append where the key represents the
        name of the processor and value is the function pointer to the new
        processor.

    Returns:
      A dictionary which represents the new processing pipeline.
    """
    updated_processors = dict(processors)
    for name, processor in new_processors.items():
        updated_processors[name] = processor

    return updated_processors

def _replace(processors, **new_processors):
    """Replace processors in a given processing pipeline.

    Args:
      processors: The dictionary representing the processing pipeline.
      **new_processors: The processors to override where the key represents the
        name of the processor and value is the function pointer to the new
        processor.

    Returns:
      A dictionary which represents the new processing pipeline.
    """
    updated_processors = dict(processors)
    for name, processor in new_processors.items():
        if name not in processors:
            fail("Error, %s not found, unable to override." % name)

        # NOTE: Overwriting an existing value does not break iteration order.
        # However, if a new processor is being added that needs to be injected
        # between other processors, the processing pipeline dictionary will need
        # to be recreated.
        updated_processors[name] = processor

    return updated_processors

processing_pipeline = struct(
    make_processing_pipeline = _make_processing_pipeline,
    run = _run,
    prepend = _prepend,
    append = _append,
    replace = _replace,
)
