<class name="UserStatechart">
    <relationships>
        <association name="parent" class="MvKController" min="1" max="1"/>
    </relationships>
    <constructor>
        <parameter name="username"/>
        <body>
            <![CDATA[
            self.username = username

            self.output_queue = []
            self.source_execution = None

            self.request_id = 0
            self.outstanding_execution = None
            self.outstanding_input = {}
            self.outstanding_output = None
            ]]>
        </body>
    </constructor>
    <scxml initial="init">
        <state id="init">
            <transition event="set_returnpath" target="../running">
                <parameter name="returnpath"/>
                <script>
                    self.returnpath = returnpath
                </script>
            </transition>
        </state>

        <parallel id="running">
            <state id="execution" initial="init">
                <state id="init">
                    <onentry>
                        <raise event="execute" scope="narrow" target="'parent/executor'">
                            <parameter expr="self.returnpath"/>
                            <parameter expr="self.username"/>
                            <parameter expr="'execute_rule'"/>
                            <parameter expr="[]"/>
                            <parameter expr="self.request_id"/>
                        </raise>
                        <script>
                            self.outstanding_execution = self.request_id
                            self.request_id += 1
                        </script>
                    </onentry>
                    <transition event="executed" cond="success and self.outstanding_execution == request_id" target=".">
                        <parameter name="returnvalue"/>
                        <parameter name="success"/>
                        <parameter name="request_id"/>
                    </transition>
                    <transition event="executed" cond="not success and self.outstanding_execution == request_id" target="../timeout">
                        <parameter name="returnvalue"/>
                        <parameter name="success"/>
                        <parameter name="request_id"/>
                    </transition>
                </state>

                <state id="timeout">
                    <transition after="1.0" target="../init"/>
                    <transition event="set_input_done" target="../init"/>
                </state>
            </state>

            <state id="set_input" initial="fetch">
                <state id="fetch">
                    <transition event="set_input" target=".">
                        <parameter name="source"/>
                        <parameter name="args"/>
                        <raise event="execute" scope="narrow" target="'parent/executor'">
                            <parameter expr="self.returnpath"/>
                            <parameter expr="self.username"/>
                            <parameter expr="'set_input'"/>
                            <parameter expr="args"/>
                            <parameter expr="self.request_id"/>
                        </raise>
                        <script>
                            self.outstanding_input[self.request_id] = source
                            self.request_id += 1
                        </script>
                    </transition>
                    <transition event="executed" cond="request_id in self.outstanding_input" target=".">
                        <parameter name="returnvalue"/>
                        <parameter name="success"/>
                        <parameter name="request_id"/>
                        <script>
                            source = self.outstanding_input.pop(request_id)
                        </script>
                        <raise event="HTTP_input" scope="narrow" target="'parent/to_mvi/' + source">
                            <parameter expr="returnvalue"/>
                        </raise>
                        <raise event="set_input_done"/>
                    </transition>
                </state>
            </state>

            <state id="get_output_queue">
                <state id="waiting">
                    <transition event="get_output" target=".">
                        <parameter name="source"/>
                        <parameter name="args"/>
                        <script>
                            self.output_queue.append(source)
                        </script>
                    </transition>
                </state>
            </state>

            <state id="get_output" initial="try_execute">
                <state id="try_execute">
                    <transition cond="self.outstanding_output is None and self.output_queue" target=".">
                        <raise event="execute" scope="narrow" target="'parent/executor'">
                            <parameter expr="self.returnpath"/>
                            <parameter expr="self.username"/>
                            <parameter expr="'get_output'"/>
                            <parameter expr="[]"/>
                            <parameter expr="self.request_id"/>
                        </raise>
                        <script>
                            self.outstanding_output = self.request_id
                            self.request_id += 1
                        </script>
                    </transition>
                    <transition event="executed" cond="success and request_id == self.outstanding_output" target=".">
                        <parameter name="returnvalue"/>
                        <parameter name="success"/>
                        <parameter name="request_id"/>
                        <raise event="HTTP_input" scope="narrow" target="'parent/to_mvi/' + self.output_queue.pop(0)">
                            <parameter expr="returnvalue"/>
                        </raise>
                        <script>
                            self.outstanding_output = None
                        </script>
                    </transition>
                    <transition event="executed" cond="not success and request_id == self.outstanding_output" target="../waiting">
                        <parameter name="returnvalue"/>
                        <parameter name="success"/>
                        <parameter name="request_id"/>
                        <script>
                            self.outstanding_output = None
                        </script>
                    </transition>
                </state>

                <state id="waiting">
                    <transition after="1.0" target="../try_execute"/>
                </state>
            </state>
        </parallel>
    </scxml>
</class>
