#!/usr/bin/env python3
# Copyright 2021 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Graph analysis functions for the testing framework.
"""

import logging
from typing import List, Optional, Tuple

from models import ActionCoverage
from models import ActionType
from models import Action
from models import ActionNode
from models import CoverageTest
from models import TestPlatform


def build_action_node_graph(root_node: ActionNode,
                            tests: List[CoverageTest]) -> None:
    """
    Builds a graph of ActionNodes on the given `root_node`. The graph is
    generated by iterating the `tests`, starting at the `root_node` for each
    test, and adding ActionNodes to the graph for each state-change action
    (following the graph for every state-change action). State-check actions are
    added to the previous state-change action ActionNode.
    """
    assert root_node is not None
    assert isinstance(root_node, ActionNode)
    assert isinstance(tests, list)
    for test in tests:
        assert isinstance(test, CoverageTest)
        parent = root_node
        for action in test.actions:
            assert isinstance(action, Action)
            assert action.type is not ActionType.PARAMETERIZED
            if action.is_state_check():
                parent.add_state_check_action(action)
            else:
                node = None
                if action.name in parent.children:
                    node = parent.children[action.name]
                else:
                    node = ActionNode(action)
                    parent.add_child(node)
                parent = node


def generage_graphviz_dot_file(root_node: ActionNode,
                               platform: Optional[TestPlatform]) -> str:
    def get_all_nodes_and_assign_graph_ids(root: ActionNode
                                           ) -> List[ActionNode]:
        current_graph_id = 0

        def get_all_nodes_helper(node: ActionNode, nodes: List[ActionNode]):
            nonlocal current_graph_id
            if node.graph_id is not None:
                return
            node.graph_id = current_graph_id
            current_graph_id += 1
            nodes.append(node)
            if not node.children:
                return
            for child in node.children.values():
                get_all_nodes_helper(child, nodes)

        # Skip the root node, as it is only there for the algorithm to work.
        all_nodes = []
        for child in root.children.values():
            get_all_nodes_helper(child, all_nodes)
        return all_nodes

    def print_graph(node: ActionNode) -> List[str]:
        assert node.graph_id is not None, node.action.name
        if not node.children:
            return []
        lines = []
        for child in node.children.values():
            assert child.graph_id is not None, child.action.name
            edge_str = str(node.graph_id) + " -> " + str(child.graph_id)
            lines.append(edge_str)
            lines.extend(print_graph(child))
        return lines

    lines = []
    lines.append("strict digraph {")
    nodes = get_all_nodes_and_assign_graph_ids(root_node)
    for node in nodes:
        color_str = ("seagreen" if platform is None
                     or platform in node.action.full_coverage_platforms else
                     "sandybrown")
        label_str = node.get_graphviz_label()
        lines.append(f"{node.graph_id}[label={label_str} color={color_str}]")
    # Skip the root node, as it is only there for the algorithm to work.
    for child in root_node.children.values():
        lines.extend(print_graph(child))
    lines.append("}")
    return "\n".join(lines)


# Removes any nodes and actions from the graph that are not supported by the
# given platform.
def trim_graph_to_platform_actions(root_node: ActionNode,
                                   platform: TestPlatform) -> None:
    """
    Removes any nodes and actions from the graph that are not supported by the
    given platform.
    """
    new_children = {}
    for child in root_node.children.values():
        if child.action.supported_for_platform(platform):
            new_children[child.action.name] = child
    root_node.children = new_children
    new_state_check_actions = {}
    for action in root_node.state_check_actions.values():
        if action.supported_for_platform(platform):
            new_state_check_actions[action.name] = action
    root_node.state_check_actions = new_state_check_actions
    for child in root_node.children.values():
        trim_graph_to_platform_actions(child, platform)


def generate_framework_tests(root_node: ActionNode,
                             platform: TestPlatform) -> List[CoverageTest]:
    assert isinstance(root_node, ActionNode)

    def GetAllPaths(node: ActionNode) -> List[List[ActionNode]]:
        assert node is not None
        assert isinstance(node, ActionNode)
        paths = []
        for child in node.children.values():
            for path in GetAllPaths(child):
                assert path is not None
                assert isinstance(path, list)
                assert bool(path)
                paths.append([node] + path)
        if len(paths) == 0:
            paths = [[node]]
        return paths

    all_paths = GetAllPaths(root_node)
    result = []
    for path in all_paths:
        all_actions_in_path = []
        for node in path[1:]:  # Skip the root node
            all_actions_in_path.append(node.action)
            all_actions_in_path.extend(node.state_check_actions.values())
        result.append(CoverageTest(all_actions_in_path, {platform}))
    return result


def generate_coverage_file_and_percents(
        required_coverage_tests: List[CoverageTest],
        tested_graph_root: ActionNode,
        platform: TestPlatform) -> Tuple[str, float, float]:
    lines = []
    total_actions = 0.0
    actions_fully_covered = 0.0
    actions_partially_covered = 0.0
    for coverage_test in required_coverage_tests:
        action_strings = []
        last_action_node = tested_graph_root
        for action in coverage_test.actions:
            total_actions += 1
            coverage = None
            if last_action_node is not None:
                if action.name in last_action_node.children:
                    coverage = action.get_coverage_for_platform(platform)
                if (action.is_state_check()
                        and last_action_node.has_state_check_action(action)):
                    coverage = action.get_coverage_for_platform(platform)
            if coverage is None:
                last_action_node = None
                action_strings.append(action.name + '🌑')
                continue
            elif (coverage == ActionCoverage.FULL):
                actions_fully_covered += 1
                action_strings.append(action.name + '🌕')
            elif (coverage == ActionCoverage.PARTIAL):
                action_strings.append(action.name + '🌓')
                actions_partially_covered += 1
            # Only proceed if the action was in the children. If not, then it
            # was in the stateless action list and we stay at the same node.
            if action.name in last_action_node.children:
                last_action_node = last_action_node.children[action.name]
        lines.append(action_strings)

    full_coverage = actions_fully_covered / total_actions
    partial_coverage = ((actions_fully_covered + actions_partially_covered) /
                        total_actions)
    logging.info(f"Coverage for {platform}:")
    logging.info(f"Full coverage: {full_coverage:.0%}, "
                 f", with partial coverage: {partial_coverage:.0%}")
    return ("\n".join(["\t".join(line)
                       for line in lines]), full_coverage, partial_coverage)
