from threading import (Thread, Event, Condition)


class StringQueue(object):
    """ Class used to store the buffered consoles data:
         - SerialConsole
         - TermConsole
    """
    def __init__(self):
        self.cond = Condition()
        self.string = ''

    def write(self, data):
        with self.cond:
            self.string += data
            self.cond.notify() # Wake 1 thread waiting on cond (if any)

    def writeln(self, data=''):
        self.write(data + '\n')

    def read(self, block=False, timeout=None):
        ret = ''
        with self.cond:
            # If blocking is true, always return at least 1 item
            if block and len(self.string) == 0:
                self.cond.wait(timeout)
            if len(self.string) != 0:
                ret = self.string
                self.string = ''
        return ret
    
    def flush(self):
        pass

class BufferedStringQueue(StringQueue):
    def __init__(self, stream_out):
        super().__init__()
        self.stream_out = stream_out
        self.thr_started = Event()
        self.stop_evt = Event()
        self.thrd = Thread(target=self.loop)
        self.thrd.daemon = True
        self.thrd.start()
        self.thr_started.wait()

    def stop(self):
        self.stop_evt.set()
        self.thrd.join()
        del self.stop_evt
        del self.thrd
        del self.thr_started

    def loop(self):
        self.thr_started.set()
        while not self.stop_evt.is_set():
            data = self.read(True, 0.1)
            self.stream_out.write(data)
