from panda3d.core import Geom, GeomTriangles, GeomVertexWriter
from panda3d.core import GeomVertexFormat, GeomVertexData
from panda3d.core import Vec3, Vec4, Point3,BitMask32
from panda3d.core import Texture, GeomNode

HIGHLIGHTCOLOR = Vec4(.5,.5,.5,0)
DEFAULTCOLOR = Vec4(1,1,1,0)

#you cant normalize in-place so this is a helper function
def myNormalize(myVec):
	myVec.normalize()
	return myVec

#helper function to make a square given the Lower-Left-Hand and Upper-Right-Hand corners 
def makeSquare(x1,y1,z1, x2,y2,z2):
	format=GeomVertexFormat.getV3n3cpt2()
	vdata=GeomVertexData('square', format, Geom.UHDynamic)

	vertex=GeomVertexWriter(vdata, 'vertex')
	normal=GeomVertexWriter(vdata, 'normal')
	color=GeomVertexWriter(vdata, 'color')
	texcoord=GeomVertexWriter(vdata, 'texcoord')
	
	#make sure we draw the sqaure in the right plane
	if x1!=x2:
		vertex.addData3f(x1, y1, z1)
		vertex.addData3f(x2, y1, z1)
		vertex.addData3f(x2, y2, z2)
		vertex.addData3f(x1, y2, z2)

		normal.addData3f(myNormalize(Vec3(2*x1-1, 2*y1-1, 2*z1-1)))
		normal.addData3f(myNormalize(Vec3(2*x2-1, 2*y1-1, 2*z1-1)))
		normal.addData3f(myNormalize(Vec3(2*x2-1, 2*y2-1, 2*z2-1)))
		normal.addData3f(myNormalize(Vec3(2*x1-1, 2*y2-1, 2*z2-1)))
		
	else:
		vertex.addData3f(x1, y1, z1)
		vertex.addData3f(x2, y2, z1)
		vertex.addData3f(x2, y2, z2)
		vertex.addData3f(x1, y1, z2)

		normal.addData3f(myNormalize(Vec3(2*x1-1, 2*y1-1, 2*z1-1)))
		normal.addData3f(myNormalize(Vec3(2*x2-1, 2*y2-1, 2*z1-1)))
		normal.addData3f(myNormalize(Vec3(2*x2-1, 2*y2-1, 2*z2-1)))
		normal.addData3f(myNormalize(Vec3(2*x1-1, 2*y1-1, 2*z2-1)))

	#adding different colors to the vertex for visibility
	#color.addData4f(1.0,0.0,0.0,1.0)
	#color.addData4f(0.0,1.0,0.0,1.0)
	#color.addData4f(0.0,0.0,1.0,1.0)
	#color.addData4f(1.0,0.0,1.0,1.0)

	texcoord.addData2f(0.0, 1.0)
	texcoord.addData2f(0.0, 0.0)
	texcoord.addData2f(1.0, 0.0)
	texcoord.addData2f(1.0, 1.0)

	#quads arent directly supported by the Geom interface
	#you might be interested in the CardMaker class if you are
	#interested in rectangle though
	tri1=GeomTriangles(Geom.UHDynamic)
	tri2=GeomTriangles(Geom.UHDynamic)

	tri1.addVertex(0)
	tri1.addVertex(1)
	tri1.addVertex(3)

	tri2.addConsecutiveVertices(1,3)

	tri1.closePrimitive()
	tri2.closePrimitive()


	square=Geom(vdata)
	square.addPrimitive(tri1)
	square.addPrimitive(tri2)
	return square


textures = {}
textures['grass'] = loader.loadTexture("textures/grass.png")
textures['metal'] = loader.loadTexture("textures/metal.png")
textures['dirt'] = loader.loadTexture("textures/dirt.png")


class Cube():


	def __init__(self,x,y,z,type):
		global textures

		self.x = x
		self.y = y
		self.z = z
		self.position = (x,y,z)
		self.tree = None
		self.type = type
		self.generated = False

		self.model = loader.loadModel('eggs/cube.egg')
		self.model.setPos((x,y,z))
		self.generated = True

		#self.square0=makeSquare(-1,-1,-1, 1,-1, 1)
		#self.square1=makeSquare(-1, 1,-1, 1, 1, 1)
		#self.square2=makeSquare(-1, 1, 1, 1,-1, 1)
		#self.square3=makeSquare(-1, 1,-1, 1,-1,-1)
		#self.square4=makeSquare(-1,-1,-1,-1, 1, 1)
		#self.square5=makeSquare( 1,-1,-1, 1, 1, 1)

	def generate(self):
		x = self.x
		y = self.y
		z = self.z
		type = self.type
		self.square0=makeSquare(x    ,y    ,z    ,x + 1,y    ,z + 1)
		self.square1=makeSquare(x    ,y + 1,z    ,x + 1,y + 1,z + 1)
		self.square2=makeSquare(x    ,y + 1,z + 1,x + 1,y    ,z + 1)
		self.square3=makeSquare(x    ,y + 1,z    ,x + 1,y    ,z    )
		self.square4=makeSquare(x    ,y    ,z    ,x    ,y + 1,z + 1)
		self.square5=makeSquare(x + 1,y    ,z    ,x + 1,y + 1,z + 1)

		self.snode=GeomNode('square')
		self.snode.addGeom(self.square0)
		self.snode.addGeom(self.square1)
		self.snode.addGeom(self.square2)
		self.snode.addGeom(self.square3)
		self.snode.addGeom(self.square4)
		self.snode.addGeom(self.square5)

		#print dir(render)
		#self.cube.hprInterval(1.5,Point3(360,360,360)).loop()
		self.generated = True

	def getneighbors(self):
		x = self.x
		y = self.y
		z = self.z
		return ((x,y,z+1),(x+1,y,z),(x,y+1,z),(x-1,y,z),(x,y-1,z),(x,y,z-1))

	def checkneighbors(self):
		if not self.tree:
			return True
		positions = self.getneighbors()
		for pos in positions:
			result = self.tree.search(pos)
			if not result:
				return True
		return False

	def show(self,renderNode):
		global texture
		self.rendernode = renderNode
		if not self.generated:
			self.generate()
		#self.cube = render.attachNewNode(self.snode)
		#self.cube.setTwoSided(True)
		#self.cube.setTexture(textures[self.type])
		self.model.setTexture(textures[self.type])
		self.model.reparentTo(renderNode)
		#print dir(self.model)
		self.model.setCollideMask(BitMask32.bit(1))
		self.model.setTag('cube',str(self.x) + ',' + str(self.y) + ',' + str(self.z))
	def hide(self):
		self.model.detachNode()
		#print dir(self.model)
		#self.cube.removeNode()
		pass
	def remove(self):
		self.hide()
		self.tree.remove(self.position)
		for pos in self.getneighbors():
			c = self.tree.search(pos)
			if c:
				if c.checkneighbors():
					c.show(self.rendernode)

	def settree(self,tree):
		self.tree = tree

	def highlight(self):
		print 'lighting'
		self.model.setColor(HIGHLIGHTCOLOR)
	def dehighlight(self):
		self.model.setColor(DEFAULTCOLOR)
