def ungroup_state(self, state_id):
        """ Ungroup state with state id state_id into its parent and remain internal linkage in parent.
            Interconnecting transitions and data flows to parent and other child states are preserved except:
            - a transition that is going from income to outcome directly and
            - a data-flow that is linking input and output directly.

        :param state_id: State that is to be ungrouped.
        :return:
        """
        state = self.states[state_id]
        assert isinstance(state, ContainerState)
        from rafcon.core.states.barrier_concurrency_state import BarrierConcurrencyState, UNIQUE_DECIDER_STATE_ID
        if isinstance(state, BarrierConcurrencyState):
            state.remove_state(state_id=UNIQUE_DECIDER_STATE_ID, force=True)
        [related_transitions, related_data_flows] = self.related_linkage_state(state_id)

        # ingoing logical linkage to rebuild -> related_transitions['external']['ingoing']
        # outgoing logical linkage to rebuild -> related_transitions['external']['outgoing']
        # ingoing data linkage to rebuild
        ingoing_data_linkage_for_port = {}
        for df in related_data_flows['internal']['ingoing']:
            if (df.from_state, df.from_key) in ingoing_data_linkage_for_port:
                ingoing_data_linkage_for_port[(df.from_state, df.from_key)]['internal'].append(df)
            else:
                ingoing_data_linkage_for_port[(df.from_state, df.from_key)] = {'external': [], 'internal': [df]}
            if not ingoing_data_linkage_for_port[(df.from_state, df.from_key)]['external']:
                for ext_df in self.data_flows.values():
                    if (ext_df.to_state, ext_df.to_key) == (df.from_state, df.from_key):
                        ingoing_data_linkage_for_port[(df.from_state, df.from_key)]['external'].append(ext_df)
        # outgoing data linkage to rebuild
        outgoing_data_linkage_for_port = {}
        for df in related_data_flows['internal']['outgoing']:
            if (df.to_state, df.to_key) in outgoing_data_linkage_for_port:
                outgoing_data_linkage_for_port[(df.to_state, df.to_key)]['internal'].append(df)
            else:
                outgoing_data_linkage_for_port[(df.to_state, df.to_key)] = {'external': [], 'internal': [df]}
            if not outgoing_data_linkage_for_port[(df.to_state, df.to_key)]['external']:
                for ext_df in self.data_flows.values():
                    if (ext_df.from_state, ext_df.from_key) == (df.to_state, df.to_key):
                        outgoing_data_linkage_for_port[(df.to_state, df.to_key)]['external'].append(ext_df)
        # hold states and scoped variables to rebuild
        child_states = [state.remove_state(s_id, recursive=False, destroy=False) for s_id in list(state.states.keys())]
        child_scoped_variables = [sv for sv_id, sv in list(state.scoped_variables.items())]

        # remove state that should be ungrouped
        old_state = self.remove_state(state_id, recursive=False, destroy=False)

        # fill elements into parent state and remember id mapping from child to parent state to map other properties
        state_id_dict = {}
        sv_id_dict = {}
        enclosed_df_id_dict = {}
        enclosed_t_id_dict = {}

        # re-create states
        old_state_ids = [state.state_id for state in child_states]
        for child_state in child_states:
            old_state_id = child_state.state_id
            # needed to change state id here because not handled in add state and to avoid old state ids
            new_id = None
            if child_state.state_id in list(self.states.keys()):
                new_id = state_id_generator(used_state_ids=list(self.states.keys()) + old_state_ids + [self.state_id])
                child_state.change_state_id(new_id)
            new_state_id = self.add_state(child_state)
            if new_id is not None and not new_id == new_state_id:
                logger.error("In ungroup state the changed state id should not be changed again by add_state because it"
                             " could become a old_state_id again and screw data flows and transitions.")
            # remember new and old state id relations
            state_id_dict[old_state_id] = new_state_id
        # re-create scoped variables
        for sv in child_scoped_variables:
            name = sv.name
            if name in [parent_sv.name for parent_sv in self.scoped_variables.values()]:
                name = state_id + name
            new_sv_id = self.add_scoped_variable(name, sv.data_type, sv.default_value)
            sv_id_dict[sv.data_port_id] = new_sv_id

        # re-create transitions
        for t in related_transitions['internal']['enclosed']:
            new_t_id = self.add_transition(state_id_dict[t.from_state], t.from_outcome,
                                           state_id_dict[t.to_state], t.to_outcome)
            enclosed_t_id_dict[t.transition_id] = new_t_id
        assert len(related_transitions['internal']['ingoing']) <= 1
        if related_transitions['internal']['ingoing']:
            ingoing_t = related_transitions['internal']['ingoing'][0]
            for t in related_transitions['external']['ingoing']:
                self.add_transition(t.from_state, t.from_outcome, state_id_dict[ingoing_t.to_state],
                                    ingoing_t.to_outcome)
        for ext_t in related_transitions['external']['outgoing']:
            for t in related_transitions['internal']['outgoing']:
                if (t.to_state, t.to_outcome) == (ext_t.from_state, ext_t.from_outcome):
                    try:
                        self.add_transition(state_id_dict[t.from_state], t.from_outcome,
                                            ext_t.to_state, ext_t.to_outcome)
                    except ValueError:
                        from rafcon.core.states.barrier_concurrency_state import BarrierConcurrencyState
                        if not isinstance(self, BarrierConcurrencyState):
                            logger.exception("Error while recreation of logical linkage.")

        # re-create data flow linkage
        for df in related_data_flows['internal']['enclosed']:
            # print("enclosed: ", df)
            new_df_id = self.add_data_flow(self.state_id if state_id == df.from_state else state_id_dict[df.from_state],
                                           sv_id_dict[df.from_key] if state_id == df.from_state else df.from_key,
                                           self.state_id if state_id == df.to_state else state_id_dict[df.to_state],
                                           sv_id_dict[df.to_key] if state_id == df.to_state else df.to_key)
            enclosed_df_id_dict[df.data_flow_id] = new_df_id
        for data_port_linkage in ingoing_data_linkage_for_port.values():
            for ext_df in data_port_linkage['external']:
                for df in data_port_linkage['internal']:
                    # print("ingoing: ", ext_df, df)
                    if df.to_state not in state_id_dict and df.to_state == state_id:
                        self.add_data_flow(ext_df.from_state, ext_df.from_key, self.state_id, sv_id_dict[df.to_key])
                    else:
                        self.add_data_flow(ext_df.from_state, ext_df.from_key, state_id_dict[df.to_state], df.to_key)
        for data_port_linkage in outgoing_data_linkage_for_port.values():
            for ext_df in data_port_linkage['external']:
                for df in data_port_linkage['internal']:
                    # print("outgoing: ", ext_df, df)
                    if df.from_state not in state_id_dict and df.from_state == state_id:
                        self.add_data_flow(self.state_id, sv_id_dict[df.from_key], ext_df.to_state, ext_df.to_key)
                    else:
                        self.add_data_flow(state_id_dict[df.from_state], df.from_key, ext_df.to_state, ext_df.to_key)

        self.ungroup_state.__func__.state_id_dict = state_id_dict
        self.ungroup_state.__func__.sv_id_dict = sv_id_dict
        self.ungroup_state.__func__.enclosed_df_id_dict = enclosed_df_id_dict
        self.ungroup_state.__func__.enclosed_t_id_dict = enclosed_t_id_dict

        old_state.destroy(recursive=True)
        return old_state