""" obj threads. """

import obj
import logging
import queue
import threading
import time

class Task(threading.Thread):

    def __init__(self, *args, **kwargs):
        super().__init__(None, self.run, "", [], kwargs, daemon=True)
        self._queue = queue.Queue()
        self._func = None
        self._ready = threading.Event()
        self._result = []
        self._stopped = False

    def __iter__(self):
        return self

    def __next__(self):
        for k in dir(self):
            yield k

    def parse(self, txt):
        pass

    def put(self, func, args, kwargs):
        self._queue.put((func, args, kwargs))

    def run(self):
        (func, args, kwargs) = self._queue.get()
        try:
            e = args[0]
            txt = e.txt
        except (IndexError, AttributeError):
            txt = obj.get_name(func)
        self.setName(txt)
        try:
            res = func(*args, **kwargs)
            self._result.append(res)
        except Exception as ex:
            logging.error(obj.get_exception())
        self._ready.set()
        return self._result

    def join(self, timeout=None):
        super().join(timeout)
        return self._result

    def stop(self):
        self._stopped = True
        self._queue.put(None)

    def wait(self):
        self._ready.wait()

class Tasks(obj.Object):

    def __init__(self):
        super().__init__()
        self._queue = queue.Queue()
        self._result = []
        self._stopped = False
        self._thrs = []
        self.state = obj.Object()
        self.state.maxtasks = 1
        self.state.nrtasks = 0

    def loop(self):
        while not self._stopped:
            func, args, kwargs = self._queue.get()
            if self.state.nrtasks < self.state.maxtasks:
                thr = obj.launch(func, *args, **kwargs)
                self._thrs.append(thr)
                self.state.nrtasks += 1
            
    def reaper(self):
        while not self._stopped:
           for thr in self._thrs:
               thr.join()
               self.state.nrtasks -= 1
               self._thrs.remove(thr)
           time.sleep(0.001)

    def put(self, func, *args, **kwargs):
        if self.state.nrtasks <= self.state.maxtasks:
            self._queue.put((func, args, kwargs))
        else:
            self._queue.put_nowait((func, args, kwargs))

    def start(self):
        obj.launch(self.loop)
        obj.launch(self.reaper)
