from __future__ import absolute_import, division, print_function, unicode_literals

from pi3d.constants import *
from pi3d.Buffer import Buffer

from pi3d.Shape import Shape

class Extrude(Shape):
  """ 3d model inherits from Shape
  NB this shape has an array of three Buffers representing each end face
  and the sides of the prism. Each can be textured seperately for drawing.
  """
  def __init__(self, camera=None, light=None, path=None, height=1.0, name="", x=0.0, y=0.0, z=0.0,
               rx=0.0, ry=0.0, rz=0.0, sx=1.0, sy=1.0, sz=1.0,
               cx=0.0, cy=0.0, cz=0.0):
    """uses standard constructor for Shape extra Keyword arguments:

      *path*
        Coordinates defining crossection of prism [(x0,z0),(x1,z1)..]
      *height*
        Distance between end faces in the y direction.
    """
    super(Extrude, self).__init__(camera, light, name, x, y, z, rx, ry, rz,
                                  sx, sy, sz, cx, cy, cz)

    if VERBOSE:
      print("Creating Extrude ...")

    s = len(path) if path != None else 0
    ht = height * 0.5

    self.verts = []
    self.norms = []
    self.botface = []
    self.topface = []
    self.sidefaces = []
    self.tex_coords = []
    self.edges = s
    self.ttype = GL_TRIANGLES

    minx = path[0][0]
    maxx = path[0][0]
    minz = path[0][1]
    maxz = path[0][1]

    #find min/max values for texture coords
    for p in range(0, s):
      px = path[p][0]
      pz = path[p][1]
      minx = min(minx, px)
      minz = min(minz, pz)
      maxx = max(maxx, px)
      maxz = max(maxz, pz)

    tx = 1.0 / (maxx - minx)
    tz = 1.0 / (maxz - minz)

    #vertices for sides
    for p in range(s):
      px = path[p][0]
      pz = path[p][1]
      dx = path[(p+1)%s][0] - px
      dz = path[(p+1)%s][1] - pz
      #TODO normalize these vector components, not needed for shadows = 0:2s
      for i in (-1, 1):
        self.verts.append((px, i*ht, pz))
        self.norms.append((-dz, 0.0, dx))
        self.tex_coords.append((1.0*p/s, i*0.5))

    #vertices for edges of top and bottom, bottom first (n=2s to 3s-1) 2s:3s then top (3s+1 to 4s) 3s+1:4s+1
    for i in (-1, 1):
      for p in range(s):
        px = path[p][0]
        pz = path[p][1]
        self.verts.append((px, i*ht, pz))
        self.norms.append((0.0, i, 0.0))
        self.tex_coords.append(((px - minx) * tx, (pz - minz) * tz))
      #top and bottom face mid points verts number 3*s and 4*s+1 (bottom and top respectively)
      self.verts.append(((minx+maxx)/2, i*ht, (minz+maxz)/2))
      self.norms.append((0, i, 0))
      self.tex_coords.append((0.5, 0.5))


    for p in range(s):    #sides - triangle strip
      v0, v1, v2, v3 = 2*p, 2*p+1, (2*p+2)%(2*s), (2*p+3)%(2*s)
      self.sidefaces.append((v0, v2, v1))
      self.sidefaces.append((v1, v2, v3))

    for p in range(s):    #bottom face indices - triangle fan
      self.botface.append((s, (p+1)%s, p))

    for p in range(s):    #top face indices - triangle fan
      self.topface.append((s, p, (p+1)%s))


    # sides, top, bottom
    self.buf = [Buffer(self, self.verts[0:(2*s)], self.tex_coords[0:(2*s)], self.sidefaces, self.norms[0:(2*s)]),
          Buffer(self, self.verts[(2*s):(3*s+1)], self.tex_coords[(2*s):(3*s+1)], self.botface, self.norms[(2*s):(3*s+1)]),
          Buffer(self, self.verts[(3*s+1):(4*s+2)], self.tex_coords[(3*s+1):(4*s+2)], self.topface, self.norms[(3*s+1):(4*s+2)])]

