import direct.directbase.DirectStart
from direct.task import Task
from direct.gui.DirectGui import *
from pandac.PandaModules import *
from direct.showbase.DirectObject import *

import math, random, sys, os

#this opens pstats for you. If your not running windows you
#have to put gtk-stats here instead (I think)
os.spawnl(os.P_NOWAIT, sys.path[1]+"\\bin\pstats")

random.seed()

#this connects us to the Pstats server
#to start collecting data
PStatClient.connect()

#we're gonna have three tests for pstats
#1)A ridiculous amount of polygons on the screen at the same time
#2)A python task taking a ridiculously long time
#3)A cull test by doing test 1) but offscreen
#we'll also have a normal scene to show what Panda does normally


class PstatsTester(DirectObject):
	def __init__(self):
		pass
		self.polygonNP=None
		#self.blockCard=None
		self.currState=0
		#self.polygonTest()
		#taskMgr.add(self.taskTest, "hello")
		self.fib1=0
		self.fib2=1
		self.upper=10000000
		self.lower=1 
		self.fibNumber= OnscreenText(
      			text="Calculating Fibbonacci Numbers",
      			style=1, fg=(1,1,1,1), pos=(0, 0),
      			align=TextNode.ACenter, scale = .2)
		self.customCollector=PStatCollector("Square root of 37")

		self.currGuessDisplay=None;

		self.fibNumber.reparentTo(hidden)

		self.accept("1", self.setState1)
		self.accept("2", self.setState2)
		self.accept("3", self.setState3)
		self.accept("4", self.setState4)
		self.accept("arrow_up", self.increasePots)
		self.accept("arrow_down", self.decreasePots)
		taskMgr.add(self.updateState, "State Updater")

		title = OnscreenText(text="Panda3D: Tutorial - Using Pstats",
                       style=1, fg=(1,1,1,1),
                       pos=(0,-0.95), scale = .07)
		escapeEvent = OnscreenText( 
 			 text="ESC: Quit",
     			 style=1, fg=(1,1,1,1), pos=(-1.3, 0.95),
			 align=TextNode.ALeft, scale = .05)
		drawEvent = OnscreenText(
      			text="1: Render 1000 Teapots (Draw Test)",
      			style=1, fg=(1,1,1,1), pos=(-1.3, 0.90),
      			align=TextNode.ALeft, scale = .05)
		appEvent = OnscreenText(
      			text="2: Calculate Fibbonacci Numbers (App test)",
      			style=1, fg=(1,1,1,1), pos=(-1.3, 0.85),
      			align=TextNode.ALeft, scale = .05)
		cullEvent = OnscreenText(
      			text="3: Draw 1000 teapots offscreen (Cull Test)",
      			style=1, fg=(1,1,1,1), pos=(-1.3, 0.80),
      			align=TextNode.ALeft, scale = .05)
		customEvent = OnscreenText(
      			text="4: Use Custom Pstats Collector for Slow Square Root Function",
      			style=1, fg=(1,1,1,1), pos=(-1.3, 0.75),
      			align=TextNode.ALeft, scale = .05)
		upDownEvent = OnscreenText(
      			text="Up/Down: Increase/Decrease teapots by 100",
      			style=1, fg=(1,1,1,1), pos=(-1.3, 0.65),
      			align=TextNode.ALeft, scale = .05)


	
	def setState1(self):
		self.currState=1
		self.fibNumber.reparentTo(hidden)	
	
	def setState2(self):
		self.currState=2
		if self.polygonNP!=None:
			self.polygonNP.reparentTo(hidden)
		self.fibNumber.reparentTo(aspect2d)

	def setState3(self):
		self.currState=3
		self.fibNumber.reparentTo(hidden)

	def setState4(self):
		self.currState=4
		self.fibNumber.reparentTo(hidden)
		if self.polygonNP!=None:
			self.polygonNP.reparentTo(hidden)

	def increasePots(self):
		if self.polygonNP ==None:
			return

		for i in range(100):
			teapot=loader.loadModelCopy('teapot')
			teapot.reparentTo(self.polygonNP)
			randomX=125*(2*random.random()-1)
			randomY=125*(2*random.random()-1)
			randomZ=125*(2*random.random()-1)

			teapot.setPos(randomX, randomY, randomZ)
			#teapot.hprInterval(2, Point3(360, 360,360)).loop()
	
	def decreasePots(self):
		if self.polygonNP ==None:
			return

		for i in range(100):
			if (self.polygonNP.getNumChildren()>0):
				self.polygonNP.getChild(0).remove()
						

	def polygonTest(self):
		if self.polygonNP != None:
			self.polygonNP.reparentTo(render)
			self.polygonNP.setPos(0,0,0)
			return
		
		
		self.polygonNP=NodePath("Dummy Path")				
		for i in range(1000):
			teapot=loader.loadModelCopy('teapot')
			teapot.reparentTo(self.polygonNP)
			randomX=125*(2*random.random()-1)
			randomY=125*(2*random.random()-1)
			randomZ=125*(2*random.random()-1)

			teapot.setPos(randomX, randomY, randomZ)
			#teapot.hprInterval(2, Point3(360, 360,360)).loop()
		
		self.polygonNP.reparentTo(render) 

	def cullTest(self):
		self.polygonNP.reparentTo(render)
		self.polygonNP.setPos(-2000, 0, 0)
		
		#if self.blockCard!=None:
		#	print "wasn't equal to None"
		#	self.blockCard.reparentTo(render2d)
		#	return
		
		#self.blockCard=NodePath(CardMaker("blocker").generate())
		#self.blockCard.setSort(10)
		#self.blockCard.reparentTo(render2d)
		#self.blockCard.setScale(2)
		#self.blockCard.setPos(-1,0,-1)

	def taskTest(self,task,):
		if self.currState != 2:
			return Task.done 
		for i in range(10):
			sum=self.fib1+self.fib2
			self.fib1=self.fib2
			self.fib2=sum
		return Task.cont

	#we're going to really slowly apporximate the square root of 37
	def customTest(self,task):
		
		
		self.customCollector.start()

		currNumber=1000*random.random()
		currGuess=0;
		self.lower=0;
		self.upper=1000
		while currGuess != math.sqrt(currNumber):
			if self.currGuessDisplay==None:
				self.currGuessDisplay=OnscreenText(
      				text="Calculating Square Root of "+str(currNumber)+"\n Current Guess is:"+str(0),
      				style=1, fg=(1,1,1,1), pos=(0, 0),
      				align=TextNode.ACenter, scale = .2, mayChange=True)
			
				self.currGuessDisplay.reparentTo(aspect2d)
			
			if self.currState!=4:
				self.customCollector.stop()
				self.currGuessDisplay.reparentTo(hidden)
				self.currGuessDisplay=None
				return Task.done

			currGuess=(self.lower +self.upper)/2.0

			#print self.currGuessDisplay
			self.currGuessDisplay.setText("Calculating Square Root of "+str(currNumber)+"\n Current Guess is:"+str(currGuess))
		
			if (currGuess*currGuess) > currNumber:
				self.upper=currGuess

			elif (currGuess*currGuess) < currNumber:
				self.lower=currGuess
		
		
		self.customCollector.stop()
		return Task.cont
		
	def updateState(self, task):
		if self.currState==0:
			pass
		
		if self.currState==1:
			self.polygonTest()
		
		if self.currState==2:
			taskMgr.add(self.taskTest, "task test")

		if self.currState==3:
			self.cullTest()

		
		if self.currState==4:
			taskMgr.add(self.customTest, "custom test")
	
		return Task.cont
		
		
p=PstatsTester()

run()