"""
This module specializes Processor to calculate the frequency of the topic
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import collections
import sys

from .processor import Processor


class Counter(Processor):
    """
    Provides a Processor to obtain the topic frequency
    """
    def __init__(self, queue,
                 clear = False,
                 average_window = 1e9,
                 print_frequency_hz = 10):
        """
        Constructs a Counter.

        :param queue: Message queue
        :param clear: Clear the screen after printing every message
        :param average_window: Window (in ns) over which the message rate will
        be averaged
        :param print_frequency_hz: Terminal print frequency in msg/s
        """
        super(Counter, self).__init__(queue)
        self._msg_counter = 0
        self._clear = clear
        self.average_window = average_window
        self._timestamp_queue=collections.deque()
        self.print_period_ns = 1/print_frequency_hz*1e9
        self.last_printed = 0

    def _trim_timestamp_queue(self, msgs_in_queue):
        """
        Trims the timestamp queue until all messages are contained in the
        averaging window.

        :param msgs_in_queue: Initial number of messages in the queue. This value
        is returned with the final size of the queue, after the trimming.
        """
        while self._timestamp_queue[-1] - self._timestamp_queue[0] >= \
              self.average_window:
            self._timestamp_queue.popleft()
            msgs_in_queue -= 1
        return msgs_in_queue

    def _print_freq_info(self,
                         time_since_last_print,
                         freq,
                         current_window_ns,
                         timestamp):
        """
        Prints the current topic frequency at the printing frequency specified
        by the the class variable print_period_ns.

        :param time_since_last_print: Time elapsed since we last printed to
        screen.
        :param freq: Topic frequency
        :param current_window_ns: Current averaging window, in ns. It might not
        be exactly the value provided by the --window argument, since it
        calculates the actual window from the timestamp of the messages
        :param timestamp: Timestamp in ns of the last messaged received.
        """
        if time_since_last_print >= self.print_period_ns:
            if self._clear:
                # ANSI excape sequence
                # \x1b[2J: Clear the screen
                # \x1b[H:  Reset cursor to 0,0
                print('\x1b[2J\x1b[H')
            print("Frequency is {:.2f} msg/second".format(freq))
            print("Average window = {:.2f} seconds".format(current_window_ns))
            print("Last message received at {:.2f} seconds".\
                  format(timestamp/1e9))
            self.last_printed = timestamp

    def process(self, timestamp):
        """
        Process the queue.

        :param timestamp: Timestamp of message, filtered by expression filter in
        Player.
        """
        self._timestamp_queue.append(timestamp)
        self._msg_counter += 1
        time_span = self._timestamp_queue[-1] - self._timestamp_queue[0]
        time_since_last_print = self._timestamp_queue[-1] - self.last_printed
        if time_span >= self.average_window:
            current_window_ns = time_span / 1e9
            freq = self._msg_counter / current_window_ns
            self._msg_counter = self._trim_timestamp_queue(self._msg_counter)
            self._print_freq_info(time_since_last_print,freq,
                                  current_window_ns,timestamp)
            sys.stdout.flush()
