from intcode import Intcode
from collections import deque


class Network:
    def __init__(self, count, code):
        self.nodes = []
        self.queues = []
        self.iddles = [0] * count
        self.nat = (0, 0)
        self.nat_timer = 0
        self.nat_history = set()
        for i in range(count):
            node = Intcode()
            node.load(code)
            node.add_input(i)
            self.nodes.append(node)
            self.queues.append(deque())

    def simulate(self, stop_on_255=False):
        while True:
            for i in range(len(self.nodes)):
                self.nodes[i].step()
                # input
                if self.nodes[i].state == "input_wait":
                    if len(self.queues[i]):
                        x, y = self.queues[i].popleft()
                        self.nodes[i].add_input(x)
                        self.nodes[i].add_input(y)
                        self.iddles[i] = 0
                    else:
                        self.nodes[i].add_input(-1)
                        self.iddles[i] += 1
                # output
                if len(self.nodes[i].outputs) >= 3:
                    self.iddles[i] = 0
                    addr = self.nodes[i].get_output()
                    x = self.nodes[i].get_output()
                    y = self.nodes[i].get_output()
                    # print(f"packet from {i} to {addr}: [{x},{y}]")
                    if addr < len(self.nodes):
                        self.queues[addr].append((x, y))
                    elif addr == 255:
                        if stop_on_255:
                            return x, y
                        else:
                            self.nat = (x, y)
                    else:
                        print(f"ERROR: illegal address {addr} generated by node {i}")

            if min(self.iddles) > 20 and self.nat_timer > 20:
                self.queues[0].append(self.nat)
                if self.nat in self.nat_history:
                    return self.nat
                else:
                    self.nat_history.add(self.nat)
                self.nat_timer = 0
                print(f"NAT sent {self.nat}")
            self.nat_timer += 1
