# !/usr/bin/python
# -*- coding: utf-8 -*-

from pyforms_gui.controls.control_base import ControlBase
from AnyQt.QtWidgets import QTreeWidget, QTreeWidgetItem, QTreeView, QAbstractItemView, QAction
from AnyQt.QtGui import QIcon, QKeySequence
from AnyQt import QtCore

class ControlTree(ControlBase, QTreeWidget):
    """This class represents a wrapper to the QTreeWidget"""

    def __init__(self, *args, **kwargs):
        QTreeWidget.__init__(self)
        ControlBase.__init__(self, *args, **kwargs)

    def init_form(self):
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.setUniformRowHeights(True)
        self.setDragDropMode(QAbstractItemView.NoDragDrop)
        self.setDragEnabled(False)
        self.setAcceptDrops(False)

        self.model().dataChanged.connect(self.__itemChangedEvent)
        self.itemDoubleClicked.connect(self.__itemDoubleClicked)

        self.selectionChanged = self.selectionChanged
        self._items = {}
        super(ControlTree, self).init_form()

    def __repr__(self):
        return QTreeWidget.__repr__(self)

    ##########################################################################
    ############ FUNCTIONS ###################################################
    ##########################################################################

    def __add__(self, other):
        if isinstance(other, QTreeWidgetItem):
            self.invisibleRootItem().addChild(other)
        elif isinstance(other, str):
            item = QTreeWidgetItem(other)
            self.invisibleRootItem().addChild(item)
        elif isinstance(other, list):
            for x in other:
                if isinstance(x, str):
                    item = QTreeWidgetItem(x)
                    self.invisibleRootItem().addChild(item)
                else:
                    self.invisibleRootItem().addChild(x)
        else:
            item = QTreeWidgetItem(other)
            self.invisibleRootItem().addChild(item)

        # self.setFirstColumnSpanned( self.model().rowCount() - 1, self.rootIndex(), True)
        return self

    def __remove_recursively(self, parent, item_2_remove):
        if parent is None: return

        for i in range(parent.childCount()):
            child = parent.child(i)
            if child == item_2_remove:
                parent.removeChild(child)
            else:
                self.__remove_recursively(child, item_2_remove)

    def __sub__(self, other):
        if isinstance(other, int):
            if other < 0:
                indexToRemove = self.selected_row_index
            else:
                indexToRemove = other
            self.model().removeRow(indexToRemove)
        else:
            self.__remove_recursively(self.invisibleRootItem(), other)
        return self

    def save_form(self, data, path=None):
        pass

    def load_form(self, data, path=None):
        pass

    def add_popup_menu_option(self, label='', function_action=None, key=None, item=None, icon=None, submenu=None):
        """
        Add an option to the Control popup menu
        @param label:           label of the option.
        @param function_action:  function called when the option is selected.
        @param key:             shortcut key
        @param key:             shortcut key
        """
        action = super(ControlTree, self).add_popup_menu_option(label, function_action, key, submenu)

        if item is not None:

            if label == "-":
                self._items[id(item)].append(label)
            else:
                action = QAction(label, self.form)
                if icon is not None:
                    action.setIconVisibleInMenu(True)
                    action.setIcon(QIcon(icon))
                if key is not None:
                    action.setShortcut(QKeySequence(key))
                if function_action:
                    action.triggered.connect(function_action)
                    # Associate action to the item.
                    if id(item) not in self._items.keys():
                        self._items.update({id(item): []})
                    self._items[id(item)].append(action)
                ##########################
                return action
        return action

    def clear(self):
        super(ControlTree, self).clear()
        if self._popup_menu:
            self._popup_menu.clear()
        self._items = {}

    def expand_item(self, item, expand=True, parents=True):
        item.setExpanded(expand)
        if parents:
            parent = item.parent()
            while (True):
                try:
                    parent.setExpanded(expand)
                    parent = parent.parent()
                except AttributeError:
                    break

    def create_child(self, name, parent=None, icon=None):
        """
        Create a new child for to the parent item.
        If the parent is None it add to the root.
        """
        item = QTreeWidgetItem(self, [name]) if (
            parent is None) else QTreeWidgetItem(parent, [name])
        if icon is not None:
            if isinstance(icon, str):
                item.setIcon(0, QIcon(icon))
            elif isinstance(icon, QIcon):
                item.setIcon(0, icon)
        return item

    ##########################################################################
    ############ EVENTS ######################################################
    ##########################################################################

    def item_changed_event(self, item):
        pass

    def item_selection_changed_event(self):
        pass

    def item_double_clicked_event(self, item):
        pass

    def key_press_event(self, event):
        pass

    def rows_inserted_event(self, parent, start, end):
        """ This event is called every time a new row is added to the tree"""
        pass

    ##########################################################################
    ############ PROPERTIES ##################################################
    ##########################################################################

    @property
    def show_header(self):
        return self.header().isVisible()

    @show_header.setter
    def show_header(self, value):
        self.header().show() if value else self.header().hide()

    @property
    def selected_rows_indexes(self):
        result = []
        for index in self.selectedIndexes():
            result.append(index.row())
        return list(set(result))

    @property
    def selected_row_index(self):
        indexes = self.selected_rows_indexes
        if len(indexes) > 0:
            return indexes[0]
        else:
            return None

    @selected_row_index.setter
    def selected_row_index(self, value):
        self.setCurrentCell(value)

    @property
    def selected_item(self):
        return self.selectedItems()[0] if len(self.selectedItems()) > 0 else None

    @selected_item.setter
    def selected_item(self, value):
        self.setCurrentItem(value)

    @property
    def form(self):
        return self

    @property
    def value(self):
        root = self.invisibleRootItem()
        return [root.child(i) for i in range(root.childCount())]

    @value.setter
    def value(self, value):
        if isinstance(value, list):
            for x in value:
                self += x
        else:
            self += value

    @property
    def icon_size(self):
        size = self.iconSize()
        return size.width(), size.height()

    @icon_size.setter
    def icon_size(self, value):
        self.setIconSize(QtCore.QSize(*value))

    ##########################################################################
    ############ PRIVATE FUNCTIONS ###########################################
    ##########################################################################

    def __itemChangedEvent(self, item):
        self.item_changed_event(item)

    def rowsInserted(self, parent, start, end):
        super(ControlTree, self).rowsInserted(parent, start, end)
        self.rows_inserted_event(parent, start, end)

    def selectionChanged(self, selected, deselected):
        super(QTreeView, self).selectionChanged(selected, deselected)
        self.item_selection_changed_event()

    def __itemDoubleClicked(self, item, column):
        if hasattr(item, 'double_clicked_event'): item.double_clicked_event()
        self.item_double_clicked_event(item)

    def keyPressEvent(self, event):
        QTreeView.keyPressEvent(self, event)
        item = self.selected_item
        if hasattr(item, 'key_pressed_event'): item.key_pressed_event(event)
        self.key_press_event(event)

    def about_to_show_contextmenu_event(self):
        """
        Function called before open the Control popup menu
        """
        if len(self._items) > 0:  # Reset the menu and construct a new one only if there are actions for the items.
            self._popup_menu.clear()
            itemSelected = self.selectedItems()[0]

            if id(itemSelected) in self._items:
                for action in self._items[id(itemSelected)]:
                    if action == '-':
                        self._popup_menu.addSeparator()
                    else:
                        self._popup_menu.addAction(action)
                    # print("Adding action {action} to {item}".format(
                    #    action=action.text(), item=itemSelected))

    def clone_item(self, parent, item, copy_function=None):
        new_item = QTreeWidgetItem()
        for col_index in range(item.columnCount()):
            new_item.setText(col_index, item.text(col_index))
            new_item.setIcon(col_index, item.icon(col_index))
        if copy_function is not None: copy_function(item, new_item)
        parent.addChild(new_item)
        for child_index in range(item.childCount()):
            child_item = item.child(child_index)
            self.clone_item(new_item, child_item, copy_function)

    def clone_tree(self, tree, copy_function=None):

        for item in tree.value:
            self.clone_item(self.invisibleRootItem(), item, copy_function)
