from .rule import Rule


class BaseEnhancement(object):
    """
    The base class for all enhancements used by Reactor.
    Enhancements take an alert dictionary object and modify it in some way to
    enhance the alert. These are specified in each rule under the ``enhancements`` option.

    :param rule: Rule for the enhancement
    """

    def __init__(self, rule: Rule):
        self.rule = rule

    def process(self, alert: dict) -> None:
        """
        Modify the contents of an alert dictionary, in some way.
        See :py:func:`reactor.rule.get_alert_body` for the structure of the alert dictionary.

        :raises DropAlertException: To drop this alert
        """
        pass


class DropAlertException(Exception):
    """ Reactor will drop an alert if this exception type is raised by an enhancement """
    pass


class MetaDataEnhancement(BaseEnhancement):
    """
    Enhances an alert with the values of options listed in the ``metadata_fields`` option in a rule configuration.
    Defaults to ``category``, ``description``, ``owner``, and ``priority``.
    For example, if the rule configuration was: ::

        ---
        name: Example Rule
        category: foo
        owner: username
        priority: 2
        # rest of the config goes here
        ...


    Any alert from generated by the rule would include the following additional properties: ::

        {
          "category": "foo",
          "description": null,
          "owner": "username",
          "priority": 2
        }
    """
    def __init__(self, rule: Rule):
        super().__init__(rule)
        self._metadata = self.rule.conf('metadata_fields', ['category', 'description', 'owner', 'priority'])

    def process(self, alert: dict):
        for field in self._metadata:
            alert.setdefault(field, self.rule.conf(field))
