"""Run-local admission before new Event IDs; never filters accepted Event retries."""
from collections import Counter
import math
import os
import time


def default_seconds():
    return float(os.environ.get('CONTEXTRA_EVENT_COOLDOWN_SECONDS', '10'))


class EventCooldown:
    def __init__(self, seconds=None, *, clock=time.monotonic, overrides=None):
        self.seconds = default_seconds() if seconds is None else float(seconds)
        if not math.isfinite(self.seconds) or not 0 <= self.seconds <= 300:
            raise ValueError('Invalid Event cooldown.')
        self.clock = clock
        self.overrides = dict(overrides or {})
        if any(k not in ('INTRUSION','LOITERING','FALL','FIGHT','FIRE','CROWD') or
               type(v) not in (int, float) or not math.isfinite(v) or not 0 <= v <= 300
               for k, v in self.overrides.items()):
            raise ValueError('Invalid scenario Event cooldown.')
        self.last = {}
        self.metrics = Counter()

    def allow(self, scenario):
        now = self.clock()
        previous = self.last.get(scenario)
        if previous is not None and now-previous < self.overrides.get(scenario, self.seconds):
            self.metrics[scenario+'_suppressed_candidates'] += 1
            return False
        self.last[scenario] = now
        self.metrics[scenario+'_admitted'] += 1
        return True

    def status(self):
        return dict(seconds=self.seconds, overrides=dict(self.overrides), clock='monotonic', counts=dict(self.metrics))


def allow_event(engine, scenario):
    gate = getattr(engine, 'event_admission', None)
    return gate is None or gate(scenario)
