# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

"""
Built-in operation execution Workflow.
"""

from ... import workflow
from ..api import task


@workflow
def execute_operation(
        ctx,
        graph,
        interface_name,
        operation_name,
        operation_kwargs,
        run_by_dependency_order,
        type_names,
        node_template_ids,
        node_ids,
        **kwargs):
    """
    Built-in operation execution Workflow.

    :param workflow_context: workflow context
    :param graph: graph which will describe the workflow
    :param operation: operation name to execute
    :param operation_kwargs:
    :param run_by_dependency_order:
    :param type_names:
    :param node_template_ids:
    :param node_ids:
    :param kwargs:
    :return:
    """
    subgraphs = {}
    # filtering node instances
    filtered_nodes = list(_filter_nodes(
        context=ctx,
        node_template_ids=node_template_ids,
        node_ids=node_ids,
        type_names=type_names))

    if run_by_dependency_order:
        filtered_node_ids = set(node_instance.id for node_instance in filtered_nodes)
        for node in ctx.nodes:
            if node.id not in filtered_node_ids:
                subgraphs[node.id] = ctx.task_graph(
                    name='execute_operation_stub_{0}'.format(node.id))

    # registering actual tasks to sequences
    for node in filtered_nodes:
        graph.add_tasks(
            task.OperationTask(
                node,
                interface_name=interface_name,
                operation_name=operation_name,
                arguments=operation_kwargs
            )
        )

    for _, node_sub_workflow in subgraphs.items():
        graph.add_tasks(node_sub_workflow)

    # adding tasks dependencies if required
    if run_by_dependency_order:
        for node in ctx.nodes:
            for relationship in node.relationships:
                graph.add_dependency(
                    source_task=subgraphs[node.id], after=[subgraphs[relationship.target_id]])


def _filter_nodes(context, node_template_ids=(), node_ids=(), type_names=()):
    def _is_node_template_by_id(node_template_id):
        return not node_template_ids or node_template_id in node_template_ids

    def _is_node_by_id(node_id):
        return not node_ids or node_id in node_ids

    def _is_node_by_type(node_type):
        return not node_type.name in type_names

    for node in context.nodes:
        if all((_is_node_template_by_id(node.node_template.id),
                _is_node_by_id(node.id),
                _is_node_by_type(node.node_template.type))):
            yield node

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

"""
Built-in operation execution Workflow.
"""

from ... import workflow
from ..api import task


@workflow
def execute_operation(
        ctx,
        graph,
        interface_name,
        operation_name,
        operation_kwargs,
        run_by_dependency_order,
        type_names,
        node_template_ids,
        node_ids,
        **kwargs):
    """
    Built-in operation execution Workflow.

    :param workflow_context: workflow context
    :param graph: graph which will describe the workflow
    :param operation: operation name to execute
    :param operation_kwargs:
    :param run_by_dependency_order:
    :param type_names:
    :param node_template_ids:
    :param node_ids:
    :param kwargs:
    :return:
    """
    subgraphs = {}
    # filtering node instances
    filtered_nodes = list(_filter_nodes(
        context=ctx,
        node_template_ids=node_template_ids,
        node_ids=node_ids,
        type_names=type_names))

    if run_by_dependency_order:
        filtered_node_ids = set(node_instance.id for node_instance in filtered_nodes)
        for node in ctx.nodes:
            if node.id not in filtered_node_ids:
                subgraphs[node.id] = ctx.task_graph(
                    name='execute_operation_stub_{0}'.format(node.id))

    # registering actual tasks to sequences
    for node in filtered_nodes:
        graph.add_tasks(
            task.OperationTask(
                node,
                interface_name=interface_name,
                operation_name=operation_name,
                arguments=operation_kwargs
            )
        )

    for _, node_sub_workflow in subgraphs.items():
        graph.add_tasks(node_sub_workflow)

    # adding tasks dependencies if required
    if run_by_dependency_order:
        for node in ctx.nodes:
            for relationship in node.relationships:
                graph.add_dependency(
                    source_task=subgraphs[node.id], after=[subgraphs[relationship.target_id]])


def _filter_nodes(context, node_template_ids=(), node_ids=(), type_names=()):
    def _is_node_template_by_id(node_template_id):
        return not node_template_ids or node_template_id in node_template_ids

    def _is_node_by_id(node_id):
        return not node_ids or node_id in node_ids

    def _is_node_by_type(node_type):
        return not node_type.name in type_names

    for node in context.nodes:
        if all((_is_node_template_by_id(node.node_template.id),
                _is_node_by_id(node.id),
                _is_node_by_type(node.node_template.type))):
            yield node

# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements.  See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You 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. Built-in operation execution Workflow. Built-in operation execution Workflow.      :param workflow_context: workflow context     :param graph: graph which will describe the workflow     :param operation: operation name to execute     :param operation_kwargs:     :param run_by_dependency_order:     :param type_names:     :param node_template_ids:     :param node_ids:     :param kwargs:     :return: # filtering node instances # registering actual tasks to sequences # adding tasks dependencies if required