<class name="Service">
    <relationships>
        <association name="parent" class="MvKController" min="1" max="1"/>
    </relationships>
    <constructor>
        <parameter name="taskname"/>
        <parameter name="mvs_operations"/>
        <parameter name="mvk"/>
        <body>
            <![CDATA[
            self.taskname = taskname
            self.mvs_operations = mvs_operations
            self.mvk = mvk

            self.failed = False
            self.output_queue = []
            self.outputs = []
            self.do_yield = False
            ]]>
        </body>

    </constructor>

    <method name="execute_modelverse">
        <parameter name="taskname"/>
        <parameter name="operation"/>
        <parameter name="params"/>
        <body>
            <![CDATA[
            reply = None
            commands = []
            mvk = self.mvk
            mvs_operations = self.mvs_operations
            try:
                while 1:
                    commands = mvk.execute_yields(taskname, operation, params, reply)
                    if commands is None:
                        break
                    reply = [mvs_operations[command[0]](*(command[1])) for command in commands]
            except:
                import traceback
                print(traceback.format_exc())
                #TODO delete self, as the task has crashed!
                return False
            return True
            ]]>
        </body>
    </method>

    <scxml initial="start">
        <parallel id="start">
            <state id="execution" initial="running">
                <state id="running" initial="executing">
                    <state id="executing">
                        <onentry>
                            <script>
                                self.do_yield = True
                                while self.output_queue:
                                    if self.execute_modelverse(self.taskname, "get_output", []):
                                        if self.mvk.success:
                                            self.outputs.append((self.output_queue.pop(0), self.mvk.returnvalue))
                                        else:
                                            # No output left in Mv, so break
                                            break
                                    else:
                                        self.failed = True
                                        break
                            </script>
                        </onentry>

                        <transition cond="self.failed" target="../../failed"/>
                        <transition cond="self.do_yield" target="../yielded"/>
                    </state>

                    <state id="yielded">
                        <transition after="self.sccd_yield() + 0.2" target="../executing"/>
                        <transition event="processed_input" target="../executing"/>
                        <transition event="waiting_output" target="../executing"/>
                    </state>
                </state>

                <state id="failed">
                    <state id="failed">
                        <!-- TODO delete task -->
                    </state>
                </state>
            </state>

            <state id="process_events">
                <state id="process_events">
                    <transition event="input" target=".">
                        <parameter name="params"/>
                        <script>
                            for args_entry in params:
                                if not self.execute_modelverse(self.taskname, "set_input", [args_entry]):
                                    # Failed!
                                    self.failed = True
                                    break
                        </script>
                        <raise event="processed_input"/>
                    </transition>

                    <transition event="output" target=".">
                        <parameter name="params"/>
                        <script>
                            self.output_queue.append(params)
                        </script>
                        <raise event="waiting_output"/>
                    </transition>

                    <transition cond="self.outputs" target=".">
                        <script>
                            source, value = self.outputs.pop(0)
                        </script>
                        <raise event="HTTP_input" scope="narrow" target="'parent/to_mvi/%s' % source">
                            <parameter expr="json.dumps(value)"/>
                        </raise>
                    </transition>
                </state>
            </state>
        </parallel>
    </scxml>
</class>
