from datetime import time
from queue import Queue as OriginalQueue, Full
from typing import Generic

from typing_extensions import TypeVar

T = TypeVar('T')


class Queue(Generic[T], OriginalQueue[T]):
    def unget(self, item, block: bool = True, timeout: int | None = None) -> None:
        """Put an item into the head of the queue.
        If optional args 'block' is true and 'timeout' is None (the default),
        block if necessary until a free slot is available. If 'timeout' is
        a non-negative number, it blocks at most 'timeout' seconds and raises
        the Full exception if no free slot was available within that time.
        Otherwise ('block' is false), put an item on the queue if a free slot
        is immediately available, else raise the Full exception ('timeout'
        is ignored in that case).
        """
        with self.not_full:
            if self.maxsize > 0:
                if not block:
                    if self._qsize() >= self.maxsize:
                        raise Full
                elif timeout is None:
                    while self._qsize() >= self.maxsize:
                        self.not_full.wait()
                elif timeout < 0:
                    raise ValueError("'timeout' must be a non-negative number")
                else:
                    endtime = time() + timeout
                    while self._qsize() >= self.maxsize:
                        remaining = endtime - time()
                        if remaining <= 0.0:
                            raise Full
                        self.not_full.wait(remaining)
            self._unget(item)
            self.unfinished_tasks += 1
            self.not_empty.notify()

    def _unget(self, item):
        self.queue.appendleft(item)
