from visual import *
from visual.graph import *


class PhaseSpace: 
    def __init__(self,nSpinsX,nSpinsY,nLattice):
        self.tvWindow = 1
        
        self.nSpinsX = nSpinsX
        self.nSpinsY = nSpinsY

        self.nLattice = nLattice
     
        self.phasePointList = []
        self.returnMapPointList = []

        self.oldValueA = 0.0
        self.oldValueB = 0.0
        self.oldValueC = 0.0
        
        self.returnMapNumber = 5
        self.returnMapCounter = self.returnMapNumber

        



        self.window = display(title='Phase Space', width=390, height=480, x=495, y=540, center=(pi/2.0,pi/2.0,pi/2.0), background=(1.0,1.0,1.0))
        self.window.fov = pi/900.0
        self.window.forward = (-1,-1,-0.75)
        self.window.up = (0.0,0.01,1.0)

        self.window.userzoom = 1
        self.window.userspin = 1
        self.window.range = pi*1.25
        self.window.visible = 1

        self.window.select()
           
        self.axisOrigin = vector(0.0,0.0,0.0)
       
        self.xAxisLine = curve(pos=[(0.0,0.0,0.0),(pi,0.0,0.0)], color=(.7,.7,.7), visible=self.tvWindow)
        self.yAxisLine = curve(pos=[(0.0,0.0,0.0),(0.0,pi,0.0)], color=(.7,.7,.7), visible=self.tvWindow)
        self.zAxisLine = curve(pos=[(0.0,0.0,0.0),(0.0,0.0,pi)], color=(.7,.7,.7), visible=self.tvWindow)

        self.xAxislabel = label(pos=vector(pi,0,0), text='Angle 1-2', yoffset=-.001, space=.1, height=10, box=0, opacity=0, line=0, color=(0.0,0.0,0.0), visible=self.tvWindow)
        self.yAxislabel = label(pos=vector(0,pi,0), text='Angle 2-3', yoffset=-.001, space=.1, height=10, box=0, opacity=0, line=0, color=(0.0,0.0,0.0), visible=self.tvWindow)
        self.zAxislabel = label(pos=vector(0,0,pi), text='Angle 3-1', yoffset=.001, space=.1, height=10, box=0, opacity=0, line=0, color=(0.0,0.0,0.0), visible=self.tvWindow)

        self.cage = curve(pos=[(0.0,0.0,0.0),(pi,pi,0.0),(pi,0.0,pi),(0.0,pi,pi),(0.0,0.0,0.0),(pi,0.0,pi),(0.0,pi,pi),(pi,pi,0.0)], color=(.7,.7,.7), visible=self.tvWindow)

        if self.nSpinsY > 1:
            self.window2 = display(title='Phase Space 2', width=390, height=480, x=885, y=540, center=(pi/2.0,pi/2.0,pi/2.0), background=(1.0,1.0,1.0))
            self.window2.fov = pi/900.0
            self.window2.forward = (-1,-1,-0.75)
            self.window2.up = (0.0,0.01,1.0)

            self.window2.userzoom = 1
            self.window2.userspin = 1
            self.window2.range = pi*1.25
            self.window2.visible = 1
            
            self.window2.select()

            self.xAxisLine2 = curve(pos=[(0.0,0.0,0.0),(pi,0.0,0.0)], color=(.7,.7,.7), visible=self.tvWindow)
            self.yAxisLine2 = curve(pos=[(0.0,0.0,0.0),(0.0,pi,0.0)], color=(.7,.7,.7), visible=self.tvWindow)
            self.zAxisLine2 = curve(pos=[(0.0,0.0,0.0),(0.0,0.0,pi)], color=(.7,.7,.7), visible=self.tvWindow)

            self.xAxislabel2 = label(pos=vector(pi,0,0), text='Angle 1-2', yoffset=-.001, space=.1, height=10, box=0, opacity=0, line=0, color=(0.0,0.0,0.0), visible=self.tvWindow)
            self.yAxislabel2 = label(pos=vector(0,pi,0), text='Angle 2-3', yoffset=-.001, space=.1, height=10, box=0, opacity=0, line=0, color=(0.0,0.0,0.0), visible=self.tvWindow)
            self.zAxislabel2 = label(pos=vector(0,0,pi), text='Angle 3-1', yoffset=.001, space=.1, height=10, box=0, opacity=0, line=0, color=(0.0,0.0,0.0), visible=self.tvWindow)

            self.cage2 = curve(pos=[(0.0,0.0,0.0),(pi,pi,0.0),(pi,0.0,pi),(0.0,pi,pi),(0.0,0.0,0.0),(pi,0.0,pi),(0.0,pi,pi),(pi,pi,0.0)], color=(.7,.7,.7), visible=self.tvWindow)





    def addPoint(self):
        spinArray = self.nLattice.returnState()
        
        dotA = float(dot(spinArray[0][0][0],spinArray[1][0][0]))
        dotB = float(dot(spinArray[1][0][0],spinArray[2][0][0]))
        dotC = float(dot(spinArray[2][0][0],spinArray[0][0][0]))

        if self.nSpinsY > 1:
            dotD = float(dot(spinArray[0][1][0],spinArray[1][1][0]))
            dotE = float(dot(spinArray[1][1][0],spinArray[2][1][0]))
            dotF = float(dot(spinArray[2][1][0],spinArray[0][1][0]))
        else:
            dotD = 0.0
            dotE = 0.0
            dotF = 0.0

        if abs(dotA) < 1.0:     diffAngleA = arccos(dotA)
        else:                   diffAngleA = pi
        if abs(dotB) < 1.0:     diffAngleB = arccos(dotB)
        else:                   diffAngleB = pi
        if abs(dotC) < 1.0:     diffAngleC = arccos(dotC)
        else:                   diffAngleC = pi

        if abs(dotD) < 1.0:     diffAngleD = arccos(dotD)
        else:                   diffAngleD = pi
        if abs(dotE) < 1.0:     diffAngleE = arccos(dotE)
        else:                   diffAngleE = pi
        if abs(dotF) < 1.0:     diffAngleF = arccos(dotF)
        else:                   diffAngleF = pi
        
        newpos = vector(pi-diffAngleA,pi-diffAngleB,diffAngleC)
        newpos2 = vector(pi-diffAngleD,pi-diffAngleE,diffAngleF)
        
        newcolor = (diffAngleD/pi,diffAngleE/pi,diffAngleF/pi)
        newcolor2 = (diffAngleA/pi,diffAngleB/pi,diffAngleC/pi)

        self.window.select()
        self.phasePointList.append(sphere(pos=newpos, color=newcolor, radius=0.006, visible=1))

        if self.nSpinsY > 1:
            self.window2.select()
            self.phasePointList.append(sphere(pos=newpos2, color=newcolor2, radius=0.006, visible=1))    



    def returnMap(self):
        spinArray = self.nLattice.returnState()
        
        if self.returnMapCounter >0:
            self.returnMapCounter -= 1
        else:
            self.returnMapCounter = self.returnMapNumber
            
            oldA = self.oldValueA
            oldB = self.oldValueB
            oldC = self.oldValueC

            dotA = float(dot(spinArray[0][0][0],spinArray[1][0][0]))
            dotB = float(dot(spinArray[1][0][0],spinArray[2][0][0]))
            dotC = float(dot(spinArray[2][0][0],spinArray[0][0][0]))
            
            if abs(dotA) < 1.0:     diffAngleA = arccos(dotA)
            else:                   diffAngleA = pi
            if abs(dotB) < 1.0:     diffAngleB = arccos(dotB)
            else:                   diffAngleB = pi
            if abs(dotC) < 1.0:     diffAngleC = arccos(dotC)
            else:                   diffAngleC = pi
            
            newA = diffAngleA
            newB = diffAngleB
            newC = diffAngleC

            self.window.select()

            self.returnMapPointList.append(sphere(pos=(0.0,oldA,newA), color=(0.0,0.0,0.0), radius=0.005, visible=1))
            self.returnMapPointList.append(sphere(pos=(oldB,0.0,newB), color=(0.0,0.0,0.0), radius=0.005, visible=1))
            self.returnMapPointList.append(sphere(pos=(oldC,newC,0.0), color=(0.0,0.0,0.0), radius=0.005, visible=1))

            self.oldValueA = newA
            self.oldValueB = newB
            self.oldValueC = newC
            


        

##    def toggleWindow(self):
##        self.tvVisible = (self.tvWindow+1)%2
##        self.window.visible = self.tvWindow
    

    def resetPoints(self):
        for garbage in self.phasePointList:
            garbage.visible = 0
        for garbage in self.returnMapPointList:
            garbage.visible = 0

        self.phasePointList = []
        self.returnMapPointList = []




        
  
##points = [(1,2)]
##polarDot = gdots(pos=points, color=color.white)
##
##    
##for x in range(40):
##    points = [vector(1,x,sin(x))]
##    new = gdots(pos=points, color=color.white)






    
