from __future__ import print_function
import logging
import os
import subprocess
from .util import event_matches, stable_hash

LOG = logging.getLogger(__name__)


class ActionRunner(object):
    def __init__(self, config, state, asterisk):
        self.config = config
        self.state = state
        self.asterisk = asterisk

    def evaluate(self, alerts):
        if not self.config.get("enabled", False):
            return
        active_events = [a.event for a in alerts.values()]
        any_active_before = bool(self.state.get_meta("actions.any_active", False))
        any_active_now = bool(active_events)
        if any_active_now and not any_active_before:
            self._commands(self.config.get("active_commands") or [])
        if any_active_before and not any_active_now:
            self._commands(self.config.get("inactive_commands") or [])
        self.state.set_meta("actions.any_active", any_active_now)
        for index, mapping in enumerate(self.config.get("mappings") or []):
            key = mapping.get("name") or "mapping-%s-%s" % (index, stable_hash(mapping)[:8])
            triggers = mapping.get("triggers") or []
            matches = [any(event_matches(event, [pattern]) for event in active_events) for pattern in triggers]
            mode = str(mapping.get("match", "ANY")).upper()
            is_active = all(matches) if mode == "ALL" and matches else any(matches)
            was_active = self.state.get_action_state(key)
            if is_active and not was_active:
                self._commands(mapping.get("on_active") or [])
            elif was_active and not is_active:
                self._commands(mapping.get("on_clear") or [])
            self.state.set_action_state(key, is_active)

    def _commands(self, commands):
        for item in commands:
            if isinstance(item, str):
                item = {"type": "shell", "command": item}
            kind = str(item.get("type", "shell")).lower()
            if kind == "dtmf":
                for node in item.get("nodes") or []:
                    for digits in item.get("commands") or []:
                        self.asterisk.execute_dtmf(node, digits)
                continue
            command = item.get("command")
            if not command:
                continue
            env = os.environ.copy()
            env["BAYOU_RADAR_SKYWARN_ACTION"] = "1"
            # Shell execution is intentionally limited to explicit administrator configuration.
            subprocess.check_call(command, shell=True, env=env)
