from constant import *
import threading
from queue import Queue as Pipe
from waiter import Waiter


class Second_event_observer(threading.Thread, Waiter):
    blackboard = None

    def __init__(self):
        Waiter.__init__(self)
        threading.Thread.__init__(self)

    def start_join_all(self, threads):
        for thread in threads:
            thread.start()
        for thread in threads:
            thread.join()

    def run(self):
        while True:
            self.wait_until(event_second_data)
            self.blackboard.mock_filters_second.acquire()
            length = len(self.blackboard.filters_second)
            if length == 0:
                continue
            q_out, threads = self.init_chain()
            self.build_full_chain(length, q_out, threads)
            self.blackboard.mock_filters_second.release()
            threads[0].q_in = threads[-1].q_out
            threads[-1].q_out.put(0)
            self.start_join_all(threads)

    def build_full_chain(self, length, q_out, threads):
        for i in range(1, length):
            q_in = q_out
            q_out = Pipe(maxsize=1)
            th = self.blackboard.filters_second[i][0]()
            th.blackboard = self.blackboard
            th.q_in = q_in
            th.q_out = q_out
            th.type_saved, th.type_filtered = self.blackboard.filters_second[i][1]
            threads.append(th)

    def init_chain(self):
        threads = list()
        q_in = Pipe(maxsize=1)
        self.fill_first(q_in)
        q_out = Pipe(maxsize=1)
        th = self.blackboard.filters_second[0][0]()
        th.blackboard = self.blackboard
        th.q_in = q_in
        th.q_out = q_out
        th.type_saved, th.type_filtered = self.blackboard.filters_second[0][1]
        threads.append(th)
        return q_out, threads

    def fill_first(self, q_in):
        with open(self.blackboard.data[name_new], "r") as f:
            q_in.put(f.read())
