from vector import multivector
from solid import solid
from polybar import polybar

class polybox(polybar):
	margin = 0.05
	
	def __init__(self, dim=1, size=1, width=0.1, mass=1, constrain_position=False, constrain_rotation=False):
		super().__init__(dim, size, mass, constrain_position, constrain_rotation)
		
		self.radius = size
		self.width = width
		self.npoints = (2**dim)*dim
		
		self.vertices = []
		self.edges = []
		self.faces = []
		
		w = width/2
		box_vertices = [] # These will be filled in with the first n-cube we generate.
		box_edges = [] # Then we can translate and scale that to build the others.
		box_faces = []
		
		for i in range(2**dim):
			box_vertices.append(
				multivector.vectorize(
					[w if i&(1<<j) else -w for j in range(dim)]
				)
			)
			
			box_edges.extend(
				filter(None, # Strip out falsey values
					[(i,i&~(1<<j)) if i&(1<<j) else None for j in range(dim)]
				)
			)
			
			box_faces.extend(
				filter(None,
					[(i,i&~(1<<j),i&~(1<<j)&~(1<<k),i&~(1<<k)) if i&(1<<j) and i&(1<<k) else None for j in range(dim) for k in range(dim)]
				)
			)
		
		start_point = [0]*(dim)
		offset = 0
		for i in range(dim):
			for v1 in box_vertices:
				v2 = v1.clone()
				v2.data[1<<i] = size+w if v2.data[1<<i] > 0 else 0 # Stretch in this direction
				v2 += start_point
				self.vertices.append(v2)
			
			self.edges.extend(
				[(a+offset,b+offset) for (a,b) in box_edges] # Don't count from zero every time
			)
			
			self.faces.extend(
				[(a+offset,b+offset,c+offset,d+offset) for (a,b,c,d) in box_faces]
			)
			
			offset += len(box_vertices)
			start_point[i] += size
			if i < dim-1:
				start_point[i+1] += self.margin # Adding a little bit of margin between bars
	
#	def rotate(self, rotor):
#		B = rotor
#		Bt = ~rotor # Cache this to avoid taking the reverse for each vertex
#		self.vertices = [B@v@Bt for v in self.vertices]
	
	def internal_point(self, n):
		return self.vertices[n].vector()
	
	def get_edges(self):
		return self.edges
	
	def get_faces(self):
		return self.faces