#!/usr/bin/python
from ..nodes.base_node import BaseNode
from ..nodes.port_node import PortInputNode, PortOutputNode
from ..qgraphics.node_group import GroupNodeItem


class GroupNode(BaseNode):
    """
    `Implemented in` ``v0.2.0``

    The ``NodeGraphQt.GroupNode`` class extends from the :class:`NodeGraphQt.BaseNode`
    class with the ability to nest other nodes inside of it.

    .. inheritance-diagram:: NodeGraphQt.GroupNode

    .. image:: ../_images/group_node.png
        :width: 250px

    -
    """

    NODE_NAME = "Group"

    def __init__(self, qgraphics_item=None):
        super(GroupNode, self).__init__(qgraphics_item or GroupNodeItem)
        self._input_port_nodes = {}
        self._output_port_nodes = {}

    @property
    def is_expanded(self):
        """
        Returns if the group node is expanded or collapsed.

        Returns:
            bool: true if the node is expanded.
        """
        if not self.graph:
            return False
        return bool(self.id in self.graph.sub_graphs)

    def get_sub_graph(self):
        """
        Returns the sub graph controller to the group node if initialized
        or returns None.

        Returns:
            SubGraph: sub graph controller.
        """
        return self.graph.sub_graphs.get(self.id)

    def get_sub_graph_session(self):
        """
        Returns the serialized sub graph session.

        Returns:
            dict: serialized sub graph session.
        """
        return self.model.subgraph_session

    def set_sub_graph_session(self, serialized_session):
        """
        Sets the sub graph session data to the group node.

        Args:
            serialized_session (dict): serialized session.
        """
        serialized_session = serialized_session or {}
        self.model.subgraph_session = serialized_session

    def expand(self):
        """
        Expand the group node session.

        See Also:
            :meth:`NodeGraph.expand_group_node`,
            :meth:`SubGraph.expand_group_node`.

        Returns:
            SubGraph: node graph used to manage the nodes expaneded session.
        """
        sub_graph = self.graph.expand_group_node(self)
        return sub_graph

    def collapse(self):
        """
        Collapse the group node session it's expanded child sub graphs.

        See Also:
            :meth:`NodeGraph.collapse_group_node`,
            :meth:`SubGraph.collapse_group_node`.
        """
        self.graph.collapse_group_node(self)

    def set_name(self, name=""):
        super(GroupNode, self).set_name(name)
        # update the tab bar and navigation labels.
        sub_graph = self.get_sub_graph()
        if sub_graph:
            nav_widget = sub_graph.navigation_widget
            nav_widget.update_label_item(self.name(), self.id)

            if sub_graph.parent_graph.is_root:
                root_graph = sub_graph.parent_graph
                tab_bar = root_graph.widget.tabBar()
                for idx in range(tab_bar.count()):
                    if tab_bar.tabToolTip(idx) == self.id:
                        tab_bar.setTabText(idx, self.name())
                        break

    def add_input(
        self,
        name="input",
        multi_input=False,
        display_name=True,
        color=None,
        locked=False,
        painter_func=None,
    ):
        port = super(GroupNode, self).add_input(
            name=name,
            multi_input=multi_input,
            display_name=display_name,
            color=color,
            locked=locked,
            painter_func=painter_func,
        )
        if self.is_expanded:
            input_node = PortInputNode(parent_port=port)
            input_node.NODE_NAME = port.name()
            input_node.model.set_property("name", port.name())
            input_node.add_output(port.name())
            sub_graph = self.get_sub_graph()
            sub_graph.add_node(input_node, selected=False, push_undo=False)

        return port

    def add_output(
        self,
        name="output",
        multi_output=True,
        display_name=True,
        color=None,
        locked=False,
        painter_func=None,
    ):
        port = super(GroupNode, self).add_output(
            name=name,
            multi_output=multi_output,
            display_name=display_name,
            color=color,
            locked=locked,
            painter_func=painter_func,
        )
        if self.is_expanded:
            output_port = PortOutputNode(parent_port=port)
            output_port.NODE_NAME = port.name()
            output_port.model.set_property("name", port.name())
            output_port.add_input(port.name())
            sub_graph = self.get_sub_graph()
            sub_graph.add_node(output_port, selected=False, push_undo=False)

        return port

    def delete_input(self, port):
        if type(port) in [int, str]:
            port = self.get_input(port)
            if port is None:
                return

        if self.is_expanded:
            sub_graph = self.get_sub_graph()
            port_node = sub_graph.get_node_by_port(port)
            if port_node:
                sub_graph.remove_node(port_node, push_undo=False)

        super(GroupNode, self).delete_input(port)

    def delete_output(self, port):
        if type(port) in [int, str]:
            port = self.get_output(port)
            if port is None:
                return

        if self.is_expanded:
            sub_graph = self.get_sub_graph()
            port_node = sub_graph.get_node_by_port(port)
            if port_node:
                sub_graph.remove_node(port_node, push_undo=False)

        super(GroupNode, self).delete_output(port)
