"""Menschliche Reaktionszeit statt Frame-exakter Antwort.

Heilungen, die 45 ms nach dem Schwellenwert feuern, sind ein maschinelles
Muster. ReactionGate verzoegert den Ausloeser einmalig um eine Reaktions-
zeit; verschwindet die Bedingung vorher, wird verworfen — genau wie ein
Mensch, der nicht rechtzeitig reagiert.

Verteilung: Basis gauss(0.35, 0.15) geklemmt auf 150–1200 ms, plus eine
"abgelenkte" langsame Tail in ~12 % der Faelle (bis 3,5 s). Ein Mensch
reagiert eben NICHT immer innerhalb 600 ms — ein hartes Fenster ohne
langsame Ausreisser waere ueber viele Proben selbst ein Bot-Signal.

Notfall-Regel: Mit `urgent=True` (z. B. HP unter 50 %) faellt die
Ablenkungs-Tail komplett weg und die Reaktion dauert maximal `hi`
(1,2 s) — auch eine bereits laufende lange Verzoegerung wird gekuerzt.

Config per Env:
  TIBIAPILOT_REACTION=0   -> altes, Frame-exaktes Verhalten
"""
import os
import random
import time

REACTION_ENV = 'TIBIAPILOT_REACTION'


class ReactionGate:
    def __init__(self, mean=0.35, sigma=0.15, lo=0.15, hi=1.2,
                 distractionRate=0.12, distractionMean=1.4,
                 distractionSigma=0.5, distractionHi=3.5):
        self.enabled = os.getenv(REACTION_ENV, '1') != '0'
        self.mean = mean
        self.sigma = sigma
        self.lo = lo
        self.hi = hi
        self.distractionRate = distractionRate
        self.distractionMean = distractionMean
        self.distractionSigma = distractionSigma
        self.distractionHi = distractionHi
        self.since = None
        self.delay = 0.0

    def _sampleDelay(self):
        delay = min(max(random.gauss(self.mean, self.sigma), self.lo), self.hi)
        if random.random() < self.distractionRate:
            extra = max(random.gauss(self.distractionMean, self.distractionSigma), 0)
            delay = min(delay + extra, self.distractionHi)
        return delay

    def ready(self, condition=True, now=None, urgent=False):
        if not self.enabled:
            return bool(condition)
        if not condition:
            self.since = None
            return False
        now = time.time() if now is None else now
        if self.since is None:
            self.since = now
            self.delay = self._sampleDelay() if not urgent else self._sampleUrgentDelay()
            return False
        if urgent and self.delay > self.hi:
            # Notfall-Regel: unter kritischer HP wartet keine Ablenkung —
            # eine laufende lange Verzoegerung wird auf hi gekuerzt.
            self.delay = self.hi
        if now - self.since >= self.delay:
            self.since = None
            return True
        return False

    def _sampleUrgentDelay(self):
        """Kritischer Fall (z. B. HP < 50 %): keine Ablenkungs-Tail."""
        return min(max(random.gauss(self.mean, self.sigma), self.lo), self.hi)
