""" The extraction and storage methods for the internal Perun call graph format. While
angr call graph provider extracts the call graph from a binary file or the current project version,
the Perun call graph provider handles storage of the internal call graph format in the 'stats'
and loading call graphs from previous project versions.
"""


import perun.logic.temp as temp
import perun.logic.stats as stats
from perun.utils.helpers import SuppressedExceptions
from perun.utils.exceptions import StatsFileNotFoundException


def extract(stats_name, exclude_self, vcs_version, **_):
    """ Load the call graph of latest previous version that has the file stored in 'stats'.

    :param str stats_name: name of the call graph file
    :param bool exclude_self: specifies whether to also search in the current version directory
    :param str vcs_version: specifies minor_version to search in

    :return dict: the internal Perun call graph format
    """
    if vcs_version is None:
        # Search for the closest stats if no version is specified
        return stats.get_latest(
            stats_name, ['perun_cg'], exclude_self=exclude_self
        ).get('perun_cg', {})

    return stats.get_stats_of(stats_name, minor_version=vcs_version).get('perun_cg', {})


def store(stats_name, call_graph, cache, **_):
    """ Store the internal call graph structure into the 'stats' directory

    :param str stats_name: name of the stats file
    :param CallGraphResource call_graph: the internal call graph format
    :param bool cache: sets the cache on / off configuration
    """
    if cache:
        # Do not save the file again if it already exists
        with SuppressedExceptions(StatsFileNotFoundException):
            stats.get_stats_file_path(stats_name, check_existence=True)
            return

    serialized = {
        'call_graph': {
            'cg_map': call_graph.cg_map,
            'recursive': list(call_graph.recursive)
        },
        'control_flow': call_graph.cfg,
        'minor_version': call_graph.minor
    }
    stats.add_stats(stats_name, ['perun_cg'], [serialized])
    temp.store_temp('optimization/{}.json'.format(stats_name), serialized, json_format=True)
