#!/usr/bin/env python
"""
A PyQt OpenGL widget for displaying parts, used primarly for
debugging / optimizing part rendering.

Hazen 11/15
"""

import math
import numpy
import sys

from OpenGL import GL, GLU
from PyQt4 import QtCore, QtGui, QtOpenGL

import opensdraw.lcad_lib.colorsParser as colorsParser
import opensdraw.lcad_lib.datFileParser as datFileParser
import opensdraw.lcad_lib.glParser as glParser

all_colors = colorsParser.loadColors()

## GLWidget
#
# The GL widget for displaying a part.
#
class GLWidget(QtOpenGL.QGLWidget):

    ## __init__
    #
    # @param parent The PyQT parent of this widget.
    #
    def __init__(self, parent):
        QtOpenGL.QGLWidget.__init__(self, parent)

        self.edge_color = [0, 0, 0, 1]
        self.face_color = [1, 0, 0, 1]
        self.last_pos = QtCore.QPoint()
        self.offset = numpy.array([[0], [0], [0], [0]], dtype = numpy.float32)
        self.p_matrix = None           # Projection matrix.
        self.part = None
        self.m_r_matrix = None         # Model rotation matrix.
        self.m_s_matrix = None         # Model scale matrix.
        self.m_t_matrix = None         # Model translation matrix.
        self.v_matrix = None           # View matrix.
        self.v_r_matrix = None         # View rotation matrix.
        self.verbose = True

        self.initializeMatrices()
        self.setMinimumSize(500, 500)

        gl_format = QtOpenGL.QGLFormat()
        gl_format.setAlpha(True)
        gl_format.setSamples(16)
        gl_format.setSampleBuffers(True)
        self.setFormat(gl_format)

        self.setToolTip("Left click to rotate object.\nRight click to drag object.\nScroll wheel to zoom.")

    ## freePartGL
    #
    # Free the GL associated with the part.
    #
    def freePartGL(self):
        if self.part is not None:
            self.part.freeGL()

    ## initializeGL
    #
    # Initialize OpenGL.
    #
    def initializeGL(self):

        if self.verbose:
            print 'OpenGL info'
            print ' Vendor: %s' % (GL.glGetString(GL.GL_VENDOR))
            print ' Opengl version: %s' % (GL.glGetString(GL.GL_VERSION))
            print ' GLSL Version: %s' % (GL.glGetString(GL.GL_SHADING_LANGUAGE_VERSION))
            print ' Renderer: %s' % (GL.glGetString(GL.GL_RENDERER))

        GL.glClearColor(1.0, 1.0, 1.0, 1.0)
        GL.glFrontFace(GL.GL_CCW)
        GL.glEnable(GL.GL_CULL_FACE)
        GL.glEnable(GL.GL_DEPTH_TEST)
        GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL)

    ## initializeMatrices
    #
    # Set matrices to the correct initial values.
    #
    def initializeMatrices(self):
        self.m_r_matrix = numpy.identity(4, dtype = numpy.float32)
        self.m_s_matrix = numpy.identity(4, dtype = numpy.float32)*0.01
        self.m_t_matrix = numpy.identity(4, dtype = numpy.float32)
        self.v_r_matrix = numpy.identity(4, dtype = numpy.float32)
        self.m_s_matrix[3,3] = 1.0

    ## loadPart
    #
    # @param filename The filename of the part to load.
    #
    def loadPart(self, filename, color_id):
        self.freePartGL()
        color = all_colors[str(color_id)]
        self.part = glParser.GLParser(color.getFaceColor(),
                                      color.getEdgeColor())
        datFileParser.parsePartFile(self.part, filename)
        self.initializeMatrices()
        self.updateView()
        self.updateGL()

    ## mousePressEvent
    #
    # @param event A PyQt QMouseEvent.
    #
    def mousePressEvent(self, event):