"""
NOTE (swapnil) - This class is deprecated, do NOT use for new code
"""

from collections import deque
from multiprocessing import Lock
from typing import List, Any, cast

import forcen_public_utils.checked as ch


# Default maximum queue size use -1 to set to "infinite"
_HIGHEST_ALLOWABLE_Q_SIZE = 1000000
DEFAULT_MAX_Q_SIZE = 100000


class ThreadsafeQueue(object):
    def __init__(self, maxQsize=DEFAULT_MAX_Q_SIZE):
        self._q = deque(maxlen=maxQsize)
        self._is_accessible = False
        self._lock = Lock()

    def getMaxSize(self) -> int:
        with self._lock:
            return cast(int, self._q.maxlen)

    def setMaxSize(self, maxQsize: int=DEFAULT_MAX_Q_SIZE) -> ch.Bool:
        with self._lock:
            maxQsize = max(0, min(_HIGHEST_ALLOWABLE_Q_SIZE, maxQsize))
            if maxQsize == deque.maxlen: # pyright: ignore [reportUnnecessaryComparison]
                return ch.ok(message=f"Queue size was already <{maxQsize}>")
            
            self._q = deque(self._q, maxQsize)
            return ch.ok(message=f"Max queue size updated to <{maxQsize}> successfully")

    def set_accessible(self) -> None:
        with self._lock:
            self._is_accessible = True
        
    def set_inaccessible(self) -> None:
        with self._lock:
            self._is_accessible = False

    def is_accessible(self) -> bool:
        with self._lock:
            return self._is_accessible

    def put(self, data: Any) -> ch.Bool:
        with self._lock:
            if not self._is_accessible:
                return ch.bad(message="CustomQueue: Queue access denied! Can't write to queue")
            
            self._q.append(data)
            return ch.ok()

    def get(self) -> ch.MaybeVal[Any]:
        with self._lock:
            if not self._is_accessible:
                return ch.bad(message="CustomQueue: Queue access denied, can't read")
            
            if len(self._q) > 0:
                return ch.ok(self._q.popleft())
            return ch.ok(None)

    def getAll(self) -> ch.MaybeVal[List[Any]]:
        with self._lock:
            if not self._is_accessible:
                return ch.bad(message="CustomQueue: Queue access denied! Can't read from queue")
            
            data = [ii for ii in self._q]
            self._q.clear()
            return ch.ok(data)

    def clear(self) -> None:
        with self._lock:
            self._q.clear()

    def empty(self):
        with self._lock:
            return len(self._q) == 0

    def qsize(self):
        with self._lock:
            return len(self._q)

if __name__=="__main__":
    q = ThreadsafeQueue(maxQsize=4)
    q.set_accessible()
    assert q.qsize() == 0
    assert q.empty()

    q.put(5)
    q.put(6)

    assert q.qsize() == 2
    assert not q.empty()

    assert q.get()._data == 5 # pyright: ignore [reportPrivateUsage]
    assert q.get()._data == 6 # pyright: ignore [reportPrivateUsage]
    assert q.get()._data == [] # pyright: ignore [reportPrivateUsage]

    q.put(7)
    q.put(8)
    q.put(9)
    q.put(10)

    assert q.getAll() == [7, 8, 9, 10]

    q.put(7)
    q.put(8)
    q.put(9)
    q.put(10)
    q.put(11)
    q.put(12)

    assert q.qsize() == 4
    assert q.getAll().value() == [9, 10, 11, 12]
    assert q.getAll().value() == []
    assert q.getAll().value() == []

    assert not q.put(7).has_error()
    assert not q.put(8).has_error()
    assert not q.put(9).has_error()
    assert not q.put(10).has_error()

    q.set_inaccessible()
    assert q.getAll().has_error()

    q.set_accessible()
    assert q.put(11).has_value()
    q.set_inaccessible()
    assert q.put(12).has_error()
    
    q.set_accessible()
    assert q.get().value() == 8
    assert q.get().value() == 9
    assert q.getAll().value() == [10, 11]

    assert not q.put(7).has_error()
    assert not q.put(8).has_error()
    assert not q.put(9).has_error()
    assert not q.put(10).has_error()

    assert q.qsize() == 4
    assert not q.setMaxSize(2).has_error()
    assert q.qsize() == 2
    assert q.getMaxSize() == 2
    assert q.get().value() == 9
    assert q.get().value() == 10

    assert not q.put(7).has_error()
    assert not q.put(8).has_error()
    assert q.qsize() == 2
    assert q.setMaxSize(5).has_error()
    assert q.qsize() == 2
    assert q.getMaxSize() == 5
    assert q.get().value() == 7
    assert q.get().value() == 8