'''
Created on Apr 17, 2014

@author: mandy
'''
from PyQt4.QtGui import QGraphicsLineItem, QGraphicsItem, QColor, QPolygonF, QPainterPath, QPainter, QPen, QBrush
from PyQt4.QtCore import Qt, QLineF, QPointF
from RoleNode import RoleNode, RoleCompactNode
from DirNode import DirNode
import math

class EdgeItem(QGraphicsLineItem):
    ROLE_HIERARCH_CONN = 0
    COTERIE_CONN = 1
    SEPARATE_ROLE_CONN = 2
    SEPARATE_ROLEUSER_CONN = 3
    SEPARATE_DIR_CONN = 4
    IMPLICIT_ROLE_CONN = 5
    
    def __init__(self, linetype, start, end, main):
        QGraphicsLineItem.__init__(self)
        self.main = main
        self.arrowSize = 15
        self.setFlag(QGraphicsItem.ItemIsSelectable)
        self.type = linetype
        self.startItem = start
        self.endItem = end
        self.setZValue((-1000.0))
        self.highlighted = False
        self.setVisible(True)
        self.lineWidth = 2.0

        self.color = Qt.black
        self.arrowHead = QPolygonF()
        self.setVisible(False)
        
    def shape(self):
        angle = self.line().angle()
        if angle < 0:
            angle += 360
        angle -= 90
        angle = math.pi * angle / 180.0
        xTrans = 4 * math.cos(angle)
        yTrans = 4 * math.sin(angle)
        lower_line = self.line().translated(-xTrans,-yTrans)
        upper_line = self.line().translated(xTrans, yTrans)
        path = QPainterPath(upper_line.p1())
        path.lineTo(lower_line.p1())
        path.lineTo(lower_line.p2())
        path.lineTo(upper_line.p2())
        path.lineTo(upper_line.p1())
        path.addPolygon(self.arrowHead)
        return path
    
    def paint(self, painter, option, widget=None):
        painter.setRenderHint(QPainter.HighQualityAntialiasing, True)
        
        if self.type == self.IMPLICIT_ROLE_CONN:
            pen = QPen(Qt.gray, self.lineWidth, Qt.DashLine)
        else:
            pen = QPen(self.color)
        pen.setWidth(self.lineWidth)
        painter.setPen(pen)
        painter.setBrush(QBrush(self.color))
        
        if (isinstance(self.endItem, RoleNode) and self.type == self.ROLE_HIERARCH_CONN) or \
        (isinstance(self.endItem, RoleCompactNode) and self.type == self.SEPARATE_ROLE_CONN) or \
        (isinstance(self.endItem, DirNode) and self.type == self.SEPARATE_DIR_CONN) or \
        self.type == self.SEPARATE_ROLEUSER_CONN or self.type == self.IMPLICIT_ROLE_CONN:  
            centerline = QLineF(self.startItem.pos(), self.endItem.pos())
            startRect = self.endItem.boundingRect()
            endRect = self.endItem.boundingRect()
            
            # test the intersection between centerline and startRect
            p1 = startRect.topLeft() + self.startItem.pos()
            p2 = startRect.bottomLeft() + self.startItem.pos()
            intersection1 = QPointF()
            intersectType = QLineF(p1,p2).intersect(centerline, intersection1)
            if intersectType != QLineF.BoundedIntersection:
                p1 = p2
                p2 = startRect.bottomRight() + self.startItem.pos()
                intersectType = QLineF(p1,p2).intersect(centerline, intersection1)
                if intersectType != QLineF.BoundedIntersection:
                    p1 = p2
                    p2 = startRect.topRight() + self.startItem.pos()
                    intersectType = QLineF(p1, p2).intersect(centerline, intersection1)
                    if intersectType != QLineF.BoundedIntersection:
                        p1 = p2
                        p2 = startRect.topLeft() + self.startItem.pos()
                        intersectType = QLineF(p1, p2).intersect(centerline, intersection1)
                        if intersectType != QLineF.BoundedIntersection:
                            return
             
            intersection1 = (p1+p2) / 2.0  

            # test the intersection between centerline and endRect
            p1 = endRect.topLeft() + self.endItem.pos()
            p2 = endRect.bottomLeft() + self.endItem.pos()
            intersection2 = QPointF()
            intersectType = QLineF(p1,p2).intersect(centerline, intersection2)
            if intersectType != QLineF.BoundedIntersection:
                p1 = p2
                p2 = endRect.bottomRight() + self.endItem.pos()
                intersectType = QLineF(p1,p2).intersect(centerline, intersection2)
                if intersectType != QLineF.BoundedIntersection:
                    p1 = p2
                    p2 = endRect.topRight() + self.endItem.pos()
                    intersectType = QLineF(p1, p2).intersect(centerline, intersection2)
                    if intersectType != QLineF.BoundedIntersection:
                        p1 = p2
                        p2 = endRect.topLeft() + self.endItem.pos()
                        intersectType = QLineF(p1, p2).intersect(centerline, intersection2)
                        if intersectType != QLineF.BoundedIntersection:
                            return
            
            intersection2 = (p1+p2) / 2.0  
            self.setLine(QLineF(self.startItem.pos(), intersection2))
            
            verts = []
            verts.append(intersection2)
            if self.line().length() == 0:
                angle = 0
            else:
                angle = math.acos(self.line().dx() / self.line().length())
            if self.line().dy() >= 0:
                angle = 2*math.pi - angle
                
            verts.append( self.line().p2() +   QPointF(-math.cos(angle + math.pi / 12) * self.arrowSize,
                                                     math.sin(angle + math.pi / 12) * self.arrowSize)
                         )
            verts.append( self.line().p2() + QPointF(-math.cos(angle - math.pi / 12) * self.arrowSize,
                                                     math.sin(angle - math.pi / 12) * self.arrowSize)
                         )
            
            self.arrowHead = QPolygonF(verts)
            painter.drawPolygon(self.arrowHead)   
               
#         elif (isinstance(self.endItem, DirNode) and self.type == self.SEPARATE_DIR_CONN):  
#                 line = QLineF(self.mapFromItem(self.startItem, QPointF(0, 0)), self.mapFromItem(self.endItem, QPointF(0, 0)))
#                 self.setLine(line)
#         else:
#             self.setLine(QLineF(self.startItem.pointBottomMiddle, self.endItem.pointBottomMiddle))
        # drawing
        painter.drawLine(self.line())
        
    def updatePosition(self):
        line = QLineF(self.mapFromItem(self.startItem, QPointF(0, 0)), self.mapFromItem(self.endItem, QPointF(0, 0)))
        self.setLine(line)
        