# 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,
)
