from PyQt4 import QtCore, QtGui
from sextante.parameters.Parameter import Parameter
import os
from sextante.core.GeoAlgorithm import GeoAlgorithm
from sextante.modeler.ModelerParametersDialog import ModelerParametersDialog
from sextante.modeler.ModelerParameterDefinitionDialog import ModelerParameterDefinitionDialog

class ModelerGraphicItem(QtGui.QGraphicsItem):

    BOX_HEIGHT = 70
    BOX_WIDTH = 200

    def __init__(self, element, elementIndex, model):
        super(ModelerGraphicItem, self).__init__(None, None)
        self.model = model
        self.element = element
        self.elementIndex = elementIndex
        if isinstance(element, Parameter):
            icon = QtGui.QIcon(os.path.dirname(__file__) + "/../images/input.png")
            self.pixmap = icon.pixmap(20, 20, state=QtGui.QIcon.On)
            self.text = element.description
        else:
            self.text = element.name
            self.pixmap = element.getIcon().pixmap(20, 20, state=QtGui.QIcon.On)
        self.arrows = []
        self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
        self.setZValue(1000)

    def addArrow(self, arrow):
        self.arrows.append(arrow)

    def boundingRect(self):
        rect = QtCore.QRectF(-(ModelerGraphicItem.BOX_WIDTH + 2)/2, -(ModelerGraphicItem.BOX_HEIGHT + 2)/2,
                             ModelerGraphicItem.BOX_WIDTH + 2, ModelerGraphicItem.BOX_HEIGHT + 2)
        return rect

    def mouseDoubleClickEvent(self, event):
        self.editElement()

    def contextMenuEvent(self, event):
        popupmenu = QtGui.QMenu()
        removeAction = popupmenu.addAction("Remove")
        removeAction.triggered.connect(self.removeElement)
        editAction = popupmenu.addAction("Edit")
        editAction.triggered.connect(self.editElement)
        if isinstance(self.element, GeoAlgorithm):
            if self.elementIndex in self.model.deactivated:
                removeAction = popupmenu.addAction("Activate")
                removeAction.triggered.connect(self.activateAlgorithm)
            else:
                deactivateAction = popupmenu.addAction("Deactivate")
                deactivateAction.triggered.connect(self.deactivateAlgorithm)
        popupmenu.exec_(event.screenPos())

    def deactivateAlgorithm(self):
        self.model.deactivateAlgorithm(self.elementIndex, True)

    def activateAlgorithm(self):
        if not self.model.activateAlgorithm(self.elementIndex, True):
            QtGui.QMessageBox.warning(None, "Could not activate Algorithm",
                                   "The selected algorithm depends on other currently non-active algorithms.\nActivate them them before trying to activate it.")

    def editElement(self):
        if isinstance(self.element, Parameter):
            dlg = ModelerParameterDefinitionDialog(self.model, param = self.element)
            dlg.exec_()
            if dlg.param != None:
                self.model.updateParameter(self.elementIndex, dlg.param)
        else:
            dlg = self.element.getCustomModelerParametersDialog(self.model, self.elementIndex)
            if not dlg:
                dlg = ModelerParametersDialog(self.element, self.model, self.elementIndex)
            dlg.exec_()
            if dlg.params != None:
                self.model.updateAlgorithm(self.elementIndex, dlg.params, dlg.values, dlg.outputs)

    def removeElement(self):
        if isinstance(self.element, Parameter):
            if not self.model.removeParameter(self.elementIndex):
                QtGui.QMessageBox.warning(None, "Could not remove element",
                                   "Other elements depend on the selected one.\nRemove them before trying to remove it.")
        else:
            if not self.model.removeAlgorithm(self.elementIndex):
                QtGui.QMessageBox.warning(None, "Could not remove element",
                                   "Other elements depend on the selected one.\nRemove them before trying to remove it.")

    def getAdjustedText(self, text):
        font = QtGui.QFont("Verdana", 8)
        fm = QtGui.QFontMetricsF(font)
        w = fm.width(text)
        if w < self.BOX_WIDTH:
            return text

        text = text[0:-3] + "..."
        w = fm.width(text)
        while(w > self.BOX_WIDTH):
            text = text[0:-4] + "..."
            w = fm.width(text)
        return text


    def paint(self, painter, option, widget=None):
        rect = QtCore.QRectF(-(ModelerGraphicItem.BOX_WIDTH + 2)/2, -(ModelerGraphicItem.BOX_HEIGHT + 2)/2,
                             ModelerGraphicItem.BOX_WIDTH + 2, ModelerGraphicItem.BOX_HEIGHT + 2)
        painter.setPen(QtGui.QPen(QtCore.Qt.gray, 1))
        painter.setBrush(QtGui.QBrush(QtCore.Qt.white, QtCore.Qt.SolidPattern))
        painter.drawRect(rect)
        font = QtGui.QFont("Verdana", 8)
        painter.setFont(font)
        painter.setPen(QtGui.QPen(QtCore.Qt.black))
        fm = QtGui.QFontMetricsF(font)
        text = self.getAdjustedText(self.text)
        w = fm.width(QtCore.QString(text))
        h = fm.height()
        pt = QtCore.QPointF(-w/2, h/2)
        painter.drawText(pt, text)
        if isinstance(self.element, GeoAlgorithm):
            if self.elementIndex in self.model.deactivated:
                painter.setPen(QtGui.QPen(QtCore.Qt.red))
                w = fm.width(QtCore.QString("[deactivated]"))
                pt = QtCore.QPointF(-w/2, h+h/2)
                painter.drawText(pt, "[deactivated]")
        painter.drawPixmap(-10 , -(ModelerGraphicItem.BOX_HEIGHT )/3,self.pixmap)


    def itemChange(self, change, value):
        if change == QtGui.QGraphicsItem.ItemPositionChange:
            for arrow in self.arrows:
                arrow.updatePosition()

        return value

    def polygon(self):
        pol = QtGui.QPolygonF([
                    QtCore.QPointF(-(ModelerGraphicItem.BOX_WIDTH + 2)/2, -(ModelerGraphicItem.BOX_HEIGHT + 2)/2),
                    QtCore.QPointF(-(ModelerGraphicItem.BOX_WIDTH + 2)/2, (ModelerGraphicItem.BOX_HEIGHT + 2)/2),
                    QtCore.QPointF((ModelerGraphicItem.BOX_WIDTH + 2)/2, (ModelerGraphicItem.BOX_HEIGHT + 2)/2),
                    QtCore.QPointF((ModelerGraphicItem.BOX_WIDTH + 2)/2, -(ModelerGraphicItem.BOX_HEIGHT + 2)/2),
                    QtCore.QPointF(-(ModelerGraphicItem.BOX_WIDTH + 2)/2, -(ModelerGraphicItem.BOX_HEIGHT + 2)/2)])
        return pol

