#!/usr/bin/env python3
# Copyright 2021 The Chromium Authors. All rights reserved.
# 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)
