# -*- generated by 1.0.2 -*-
import da
PatternExpr_190 = da.pat.TuplePattern([da.pat.ConstantPattern('Out'), da.pat.SelfPattern(), da.pat.FreePattern('d')])
PatternExpr_229 = da.pat.TuplePattern([da.pat.ConstantPattern('Leader'), da.pat.FreePattern('leader')])
PatternExpr_257 = da.pat.TuplePattern([da.pat.ConstantPattern('In'), da.pat.SelfPattern()])
PatternExpr_264 = da.pat.BoundPattern('_BoundPattern265_')
PatternExpr_280 = da.pat.TuplePattern([da.pat.ConstantPattern('In'), da.pat.SelfPattern()])
PatternExpr_287 = da.pat.BoundPattern('_BoundPattern288_')
PatternExpr_309 = da.pat.TuplePattern([da.pat.ConstantPattern('Out'), da.pat.FreePattern('v'), da.pat.FreePattern('d')])
PatternExpr_318 = da.pat.FreePattern('source')
PatternExpr_353 = da.pat.TuplePattern([da.pat.ConstantPattern('In'), da.pat.FreePattern('v')])
PatternExpr_360 = da.pat.FreePattern('source')
PatternExpr_379 = da.pat.TuplePattern([da.pat.ConstantPattern('Leader'), da.pat.FreePattern('leader')])
PatternExpr_386 = da.pat.FreePattern('source')
PatternExpr_266 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern272_')]), da.pat.TuplePattern([da.pat.ConstantPattern('In'), da.pat.SelfPattern()])])
PatternExpr_289 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern295_')]), da.pat.TuplePattern([da.pat.ConstantPattern('In'), da.pat.SelfPattern()])])
_config_object = {}
import sys
import random

class P(da.DistProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._PReceivedEvent_0 = []
        self._PReceivedEvent_1 = []
        self._PReceivedEvent_2 = []
        self._PReceivedEvent_3 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_0', PatternExpr_190, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_1', PatternExpr_229, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_2', PatternExpr_257, sources=[PatternExpr_264], destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_3', PatternExpr_280, sources=[PatternExpr_287], destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_4', PatternExpr_309, sources=[PatternExpr_318], destinations=None, timestamps=None, record_history=None, handlers=[self._P_handler_308]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_5', PatternExpr_353, sources=[PatternExpr_360], destinations=None, timestamps=None, record_history=None, handlers=[self._P_handler_352]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_6', PatternExpr_379, sources=[PatternExpr_386], destinations=None, timestamps=None, record_history=None, handlers=[self._P_handler_378])])

    def setup(self, left, right, **rest_481):
        super().setup(left=left, right=right, **rest_481)
        self._state.left = left
        self._state.right = right
        pass

    def run(self):
        distance = 1
        while True:
            self.send(('Out', self._id, distance), {self._state.left, self._state.right})
            super()._label('_st_label_187', block=False)
            d = None

            def ExistentialOpExpr_188():
                nonlocal d
                for (_, _, (_ConstantPattern207_, _ConstantPattern209_, d)) in self._PReceivedEvent_0:
                    if (_ConstantPattern207_ == 'Out'):
                        if (_ConstantPattern209_ == self._id):
                            if True:
                                return True
                return False
            leader = None

            def ExistentialOpExpr_227():
                nonlocal leader
                for (_, _, (_ConstantPattern244_, leader)) in self._PReceivedEvent_1:
                    if (_ConstantPattern244_ == 'Leader'):
                        if True:
                            return True
                return False
            _st_label_187 = 0
            while (_st_label_187 == 0):
                _st_label_187 += 1
                if ExistentialOpExpr_188():
                    self.output(('I am leader at distance %d!' % d))
                    self.send(('Leader', self._id), {self._state.left, self._state.right})
                    break
                    _st_label_187 += 1
                elif ExistentialOpExpr_227():
                    self.output('Leader is', leader)
                    break
                    _st_label_187 += 1
                elif (PatternExpr_266.match_iter(self._PReceivedEvent_2, _BoundPattern272_=self._state.left, SELF_ID=self._id) and PatternExpr_289.match_iter(self._PReceivedEvent_3, _BoundPattern295_=self._state.right, SELF_ID=self._id)):
                    distance *= 2
                    for attr in dir(self):
                        if (attr.find('ReceivedEvent_') != (- 1)):
                            getattr(self, attr).clear()
                    _st_label_187 += 1
                else:
                    super()._label('_st_label_187', block=True)
                    _st_label_187 -= 1
            else:
                if (_st_label_187 != 2):
                    continue
            if (_st_label_187 != 2):
                break

    def _P_handler_308(self, v, d, source):
        if (v > self._id):
            if (d > 1):
                self.send(('Out', v, (d - 1)), (self._state.right if (source == self._state.left) else self._state.left))
            elif (d == 1):
                self.send(('In', v), source)
    _P_handler_308._labels = None
    _P_handler_308._notlabels = None

    def _P_handler_352(self, v, source):
        if (v > self._id):
            self.send(('In', v), (self._state.right if (source == self._state.left) else self._state.left))
    _P_handler_352._labels = None
    _P_handler_352._notlabels = None

    def _P_handler_378(self, leader, source):
        self.send(('Leader', leader), (self._state.right if (source == self._state.left) else self._state.left))
    _P_handler_378._labels = None
    _P_handler_378._notlabels = None

class Node_(da.NodeProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._events.extend([])
    _config_object = {'channel': 'fifo'}

    def run(self):
        n = (int(sys.argv[1]) if (len(sys.argv) > 1) else 10)
        topology = list(self.new(P, num=n))
        random.shuffle(topology)
        for (i, p) in enumerate(topology):
            if (i == (len(topology) - 1)):
                self._setup({p}, (topology[(i - 1)], topology[0]))
            else:
                self._setup({p}, (topology[(i - 1)], topology[(i + 1)]))
        self._start(topology)
