'''
Accessible Access Control 1.0
2012-2104 Michigan Technological University
Supported in part by NSF grants: DUE-1140512, DUE-1245310 and IIS-1319363
Developer: Man Wang
Advisors:Dr. Steve Carr, Dr. Jean Mayo, Dr. Ching-Kuang Shene and Dr. Chaoli Wang
'''
import math
from FileNode import FileNode

class RadialTreeLayout(object):

    def __init__(self, scene):
        self.scene = scene
        self.sceneWidth = scene.width()
        self.sceneHeight = scene.height()
    
    def calculateLeaveNumber(self, root):
        nodesToVisit = [root]
        while nodesToVisit:
            n = nodesToVisit[-1]
            if n.children:
                if n.children[0].visited:
                    n.leaves = 0
                    for c in n.children:
                        n.leaves += c.leaves
                    n.visited = True
                    nodesToVisit.pop()
                else: 
                    for c in n.children:
                        nodesToVisit.append(c)
            else:
                n.visited = True
                n.leaves = 1
                nodesToVisit.pop()
        
    def buildTreeTable(self, root, extraSpacing = 0):
        level = 0
#        for ele in self.scene.items():
#            if isinstance(ele, FileNode):
        for ele in self.scene.main.ioHelper.add2Scene.fileNodes:
                cnt = ele.fullPath.count('/')
                if cnt > level:
                    level = cnt
        level +=1
        root.leftBisectorLimit = 2*math.pi
        self.nodeTable=[[root]]
        levelNodes = root.children
        for i in xrange(1, level):
            self.nodeTable.append(levelNodes)
            for n in levelNodes:
                n.level = i
            levelNodes = []
            for n in self.nodeTable[i]:
                n.visited = False
                n.leftBisectorLimit = 2*math.pi
                for c in n.children:
                    levelNodes.append(c)
                if n.parent:
                    if n.flag == -1:
                        n.flag = n.parent.flag
                        n.type = n.parent.type
        
        self.calculateLeaveNumber(root)
        root.wedgeAngle = 2 * math.pi 

        self.numLevels = len(self.nodeTable)
        self.viewportWidth = self.scene.views()[0].viewport().width()
        self.viewportHeight = self.scene.views()[0].viewport().height()
     
        self.radius = 0.9*min(self.viewportWidth, self.viewportHeight)/ 2.0
        if self.numLevels != 0:
            self.d =  self.radius / (self.numLevels-1)

#        level=1
#        levelNodes = root.children
#        while levelNodes:
#            self.nodeTable[level] = levelNodes
#            for n in levelNodes:
#                n.level = level
#            levelNodes = []
#            for n in self.nodeTable[level]:
#                n.visited = False
#                n.leftBisectorLimit = 2*math.pi
#                if n.children:
#                    levelNodes.extend(n.children)
#            level += 1

    

    def mapToScene(self):
        edges = set()
        for nodes in self.nodeTable:
            for n in nodes:
                for e in n.edgeList:
                    edges.add(e)
#                    n.relativeX -= 14#n.boundingRect().width()*0.5
#                    n.relativeY -= 7#n.boundingRect().height()*0.5
                n.setPos(n.relativeX+self.viewportWidth/2.0+self.scene.x, -n.relativeY+self.viewportHeight/2.0+self.scene.y)#self.sceneWidth/2.0, -n.relativeY+self.sceneHeight/2.0)
        for e in edges:
            e.updatePosition()
    
#    def layout(self):
#        rootX, rootY = 0.0, 0.0
#        self.numLevels = len(self.nodeTable)
#        
##        print 'print the nodeTable ele'
##        for row in xrange(self.numLevels):
##            for ele in self.nodeTable[row]:
##                print row, ele.name
#        
#        for level in xrange(self.numLevels):
#            if level == 0:
#                rootNode = self.nodeTable[0][0]
#                rootNode.relativeX = rootX
#                rootNode.relativeY = rootY
#            elif level == 1:
#                node = self.nodeTable[1][0]
#                parent = node.parent
#                node.wedgeAngle = min(float(node.leaves)/float(parent.leaves)*parent.wedgeAngle, 2.0*math.pi/3.0)#2*math.pi/len(self.nodeTable[1])
#                node.rightLimit = -node.wedgeAngle/2.0
#                node.leftLimit = node.wedgeAngle/2.0
#                prevLeftLimit = node.leftLimit
#                node.relativeX = self.d
#                node.relativeY = 0
#                for i in xrange(1, len(self.nodeTable[1])):
#                    node = self.nodeTable[1][i]
#                    node.wedgeAngle =  min(float(node.leaves)/float(parent.leaves)*parent.wedgeAngle, 2.0*math.pi/3.0)
#                    node.angle = prevLeftLimit + node.wedgeAngle/2.0
#                    #print node.angle*180/math.pi, prevLeftLimit*180/math.pi, node.wedgeAngle*180/math.pi, parent.wedgeAngle*180/math.pi
#                    node.rightLimit = prevLeftLimit
#                    node.leftLimit = node.angle + node.wedgeAngle/2.0
#                    prevLeftLimit = node.leftLimit
#                    node.relativeX = self.d * math.cos(node.angle)
#                    node.relativeY = self.d * math.sin(node.angle)
#            else:
#                curParent = self.nodeTable[level][0].parent
#                prevLeftLimit = curParent.rightLimit
#                for node in self.nodeTable[level]:
#                    parent = node.parent
#                    if parent is not curParent:
#                        prevLeftLimit = parent.rightLimit
#                        curParent = parent
#                    node.wedgeAngle = min(float(node.leaves)/float(parent.leaves)*parent.wedgeAngle, 2.0*math.pi/3.0)
#                    node.angle = prevLeftLimit + node.wedgeAngle/2.0
#                    node.rightLimit = prevLeftLimit


    def layout(self):
        rootX = 0.0
        rootY = 0.0
        
        for level in xrange(self.numLevels):
            if level == 0:
                rootNode = self.nodeTable[0][0]
                rootNode.relativeX = rootX
                rootNode.relativeY = rootY
            elif level == 1:
                node = self.nodeTable[1][0]
                parent = node.parent
                node.wedgeAngle = min(float(node.leaves)/float(parent.leaves)*parent.wedgeAngle, 2.0*math.pi/3.0)
                #print parent.leaves, parent.wedgeAngle, node.leaves
                node.rightLimit = -node.wedgeAngle/2.0
                node.leftLimit = node.wedgeAngle/2.0
                prevLeftLimit = node.leftLimit
                node.relativeX = self.d
                node.relativeY = 0
                for i in xrange(1, len(self.nodeTable[1])):
                    node = self.nodeTable[1][i]
                    node.wedgeAngle = min(float(node.leaves)/float(parent.leaves)*parent.wedgeAngle, 2.0*math.pi/3.0)
                    node.angle = prevLeftLimit + node.wedgeAngle/2.0
                    node.rightLimit = prevLeftLimit
                    node.leftLimit = node.angle + node.wedgeAngle/2.0
                    prevLeftLimit = node.leftLimit
                    node.relativeX = self.d * math.cos(node.angle)
                    node.relativeY = self.d * math.sin(node.angle)
            else:
                curParent = self.nodeTable[level][0].parent
                prevLeftLimit = curParent.rightLimit
                for node in self.nodeTable[level]:
                    parent = node.parent
                    if parent is not curParent:
                        prevLeftLimit = parent.rightLimit
                        curParent = parent
                    node.wedgeAngle = min(float(node.leaves)/float(parent.leaves)*parent.wedgeAngle, 2.0*math.pi/3.0)
                    node.angle = prevLeftLimit + node.wedgeAngle/2.0
                    node.rightLimit = prevLeftLimit
                    node.leftLimit = node.angle + node.wedgeAngle/2.0
                    prevLeftLimit = node.leftLimit
                    node.relativeX = level*self.d*math.cos(node.angle)
                    node.relativeY = level*self.d*math.sin(node.angle)
                    
#        rootX, rootY = 0.0, 0.0
#        self.numLevels = len(self.nodeTable)
#        
##        print 'print the nodeTable ele'
##        for row in xrange(self.numLevels):
##            for ele in self.nodeTable[row]:
##                print row, ele.name
#        
#        for level in xrange(self.numLevels):
#            if level == 0:
#                rootNode = self.nodeTable[0][0]
#                rootNode.relativeX = rootX
#                rootNode.relativeY = rootY
#            elif level == 1:
#                node = self.nodeTable[1][0]
#                parent = node.parent
#                node.wedgeAngle = float(node.leaves)/float(parent.leaves)*parent.wedgeAngle#2*math.pi/len(self.nodeTable[1])
#                node.rightLimit = -node.wedgeAngle/2.0
#                node.leftLimit = node.wedgeAngle/2.0
#                prevLeftLimit = node.leftLimit
#                node.relativeX = self.d
#                node.relativeY = 0
#                for i in xrange(1, len(self.nodeTable[1])):
#                    node = self.nodeTable[1][i]
#                    node.wedgeAngle =  min(float(node.leaves)/float(parent.leaves)*parent.wedgeAngle, 2.0*math.pi/3.0)
#                    node.angle = prevLeftLimit + node.wedgeAngle/2.0
#                    #print node.angle*180/math.pi, prevLeftLimit*180/math.pi, node.wedgeAngle*180/math.pi, parent.wedgeAngle*180/math.pi
#                    node.rightLimit = prevLeftLimit
#                    node.leftLimit = node.angle + node.wedgeAngle/2.0
#                    prevLeftLimit = node.leftLimit
#                    node.relativeX = self.d * math.cos(node.angle)
#                    node.relativeY = self.d * math.sin(node.angle)
#            else:
#                curParent = self.nodeTable[level][0].parent
#                prevLeftLimit = curParent.rightLimit
#                for node in self.nodeTable[level]:
#                    parent = node.parent
#                    if parent is not curParent:
#                        prevLeftLimit = parent.rightLimit
#                        curParent = parent
#                    node.wedgeAngle = min(float(node.leaves)/float(parent.leaves)*parent.wedgeAngle, 2.0*math.pi/3.0)
#                    node.angle = prevLeftLimit + node.wedgeAngle/2.0
#                    node.rightLimit = prevLeftLimit
#                    node.leftLimit = node.angle + node.wedgeAngle/2.0
#                    prevLeftLimit = node.leftLimit
#                    node.relativeX = level*self.d*math.cos(node.angle)
#                    node.relativeY = level*self.d*math.sin(node.angle)