import collections
import time
import typing as tp
import logging

from .base import EmbeddedSubmetrics


logger = logging.getLogger(__name__)


class ClicksPerTimeUnitMetric(EmbeddedSubmetrics):
    """
    This tracks the amount of calls to handle() during the last time periods, as specified by time_unit_vectors
    (in seconds). You may specify multiple time periods as consequent entries in the list.

    By default (if you do not specify otherwise) this will track calls made during the last second.
    """
    CLASS_NAME = 'cps'

    def __init__(self, *args, time_unit_vectors: tp.Optional[tp.List[float]] = None, **kwargs):
        super().__init__(*args, time_unit_vectors=time_unit_vectors, **kwargs)
        time_unit_vectors = time_unit_vectors or [1]
        self.last_clicks = collections.deque()
        self.cutoff_period = max(time_unit_vectors)
        self.time_unit_vectors = time_unit_vectors

    def _handle(self, **labels) -> None:
        if labels or self.embedded_submetrics_enabled:
            return super()._handle(**labels)

        mono_time = time.monotonic()
        self.last_clicks.append(time.monotonic())
        try:
            while self.last_clicks[0] <= mono_time - self.cutoff_period:
                self.last_clicks.popleft()
        except IndexError:
            pass

    def to_json(self) -> tp.List[int]:
        if self.embedded_submetrics_enabled:
            return super().to_json()

        count_map = [0] * len(self.time_unit_vectors)
        mono_time = time.monotonic()
        time_unit_vectors = [mono_time - v for v in self.time_unit_vectors]

        for v in self.last_clicks:
            for index, cutoff in enumerate(time_unit_vectors):
                if v >= cutoff:
                    count_map[index] += 1

        output = []
        for time_unit, count in zip(self.time_unit_vectors, count_map):
            k = super().to_json()
            k['period'] = time_unit
            k['_'] = count
            output.append(k)

        return output
