"""
Utilities used to facilitate interfacing with process snapshot
"""
import re


def python_module(module_name):
    """
    Predicate used to search process snapshot for a group containing Python module e.g: python -m http.server

    :param module_name: python module name to find
    """
    _module_cmd_pattern = r'.*-m\s+\b{module_name}\b'.format(module_name=module_name)

    def _pred(process):
        _m = re.match(_module_cmd_pattern, process.properties.get('CmdLine', ''))
        return _m
    return _pred


def command_line_regex(pattern):
    """
    Predicate used to search process snapshot for a group that has process with command line matching a
    specified regex pattern

    :param pattern: regex pattern to find.

    """
    def _pred(process):
        cmdline = process.properties.get('CmdLine', None)
        return cmdline is not None and re.match(pattern, cmdline)
    return _pred


def pgi_name(name):
    """
    Predicate to find process group of a given name.

    :param name: name of the group
    """
    return lambda pgi: pgi.group_name == name


def parse_port_bindings(entity):
    """
    Searches entity processes for a process port bindings data

    Returns:
        list of tuple(string of binded IP address, port integer)
    """        
    bind_list = list()
    for process in entity.processes:
        to_parse = process.properties.get("PortBindings", None)
        if to_parse is None:
            continue
        for entry in to_parse.split(';'):
            entry_list = entry.split('_')
            if len(entry_list) != 2:
                continue
            bind_list.append((entry_list[0], int(entry_list[1])))
    return bind_list


def get_technologies(entity):
    """
    get technologies string list from snapshot entry
    
    Returns:
        List of string (lower case)
    """
    if not hasattr(entity, 'properties'):
        return []
    technologies = entity.properties.get ("Technologies", None)
    if technologies == None:
        return []

    tech = technologies.split(",")
    return [x.lower() for x in tech]

def get_pids(entity):
    """
        Searches entity processes for a process pid

        Returns:
            set of pids
        """
    if not hasattr(entity, 'processes'):
        return {}
    return {process.pid for process in entity.processes if process.pid}

def get_ports(entity):
    """
    Searches entity processes for process listening ports

    Returns:
        set of listening ports
    """
    port_set = set()
    if not hasattr(entity, 'processes'):
        return port_set
    for process in entity.processes:
        to_parse = process.properties.get("ListeningPorts", None)
        if to_parse is None:
            continue
        for entry in to_parse.split(' '):
            port_set.add(to_parse)
    return port_set