from defence360agent import utils
from im360.contracts.config import Subsys as Config
from im360.subsys import fail2ban
from im360.subsys import csf
from im360.subsys.panels.cpanel import cphulk


class RunningIdsDecoratedList:
    def __init__(self, ids_list):
        """
        :param list ids_list:
        """
        self.ids_list = ids_list

    def __iter__(self):
        return iter(self.ids_list)

    # is also used as a fallback when __bool__() is not found
    def __len__(self):
        return len(self.ids_list)

    def __str__(self):
        """
        Concat list so that ['csf', cphulk']
        becomes 'CSF, cPHulk' str
        """
        return ", ".join(
            ids
            for ids in Config.THIRD_PARTY_IDS
            if ids.lower() in self.ids_list
        )


@utils.cache_result(Config.THIRD_PARTY_IDS_CHECK_TIMEOUT)
async def RunningIds():
    """
    Return list of running 3rd-party IDS as RunningIds object.
    RunningIds is a decorator for builtins.list with custom __str__()

    3rd-party IDS names will be in lowercase to make parsing the list
    and further automation easier.
    """
    # Implementation was moved out because python is not OK
    # with using @classmethod or @staticmethod with decorator
    # or PeriodicCHeck while the class definition is incomplete

    services = []

    for servicename in (s.lower() for s in Config.THIRD_PARTY_IDS):
        is_running = False
        if servicename == "cphulk":
            is_running = await cphulk.is_running()
        elif servicename == "fail2ban":
            is_running = await fail2ban.is_running()
        elif servicename == "csf":
            is_running = await csf.is_running()

        if is_running:
            services.append(servicename)

    return RunningIdsDecoratedList(services)
