"""Buffer based Numpy plugin (not used)

This API is no more useful than the direct Numpy version, as Numpy already 
gives us the details we need *when using the accelerator module* at a low 
level, with very fast access.  When using the non-accelerated version the 
ctypes version *might* show some performance benefits, but it's not going 
to be fast no matter what we do without C-level code.
"""
REGISTRY_NAME = 'numpybuffers'
import operator
try:
    import numpy
except ImportError as err:
    raise ImportError( """No numpy module present: %s"""%(err))
from OpenGL.arrays import buffers
from OpenGL.raw.GL import _types 
from OpenGL.raw.GL.VERSION import GL_1_1
from OpenGL import constant, error
class NumpyHandler( buffers.BufferHandler ):
    @classmethod
    def zeros( cls, dims, typeCode ):
        """Return Numpy array of zeros in given size"""
        return numpy.zeros( dims, GL_TYPE_TO_ARRAY_MAPPING[typeCode])
    
    @classmethod
    def asArray( cls, value, typeCode=None ):
        """Convert given value to an array value of given typeCode"""
        return super(NumpyHandler,cls).asArray( cls.contiguous(value,typeCode), typeCode )
    @classmethod
    def contiguous( cls, source, typeCode=None ):
        """Get contiguous array from source

        source -- numpy Python array (or compatible object)
            for use as the data source.  If this is not a contiguous
            array of the given typeCode, a copy will be made,
            otherwise will just be returned unchanged.
        typeCode -- optional 1-character typeCode specifier for
            the numpy.array function.

        All gl*Pointer calls should use contiguous arrays, as non-
        contiguous arrays will be re-copied on every rendering pass.
        Although this doesn't raise an error, it does tend to slow
        down rendering.
        """
        typeCode = GL_TYPE_TO_ARRAY_MAPPING[ typeCode ]
        try:
            contiguous = source.flags.contiguous
        except AttributeError as err:
            if typeCode:
                return numpy.ascontiguousarray( source, typeCode )
            else:
                return numpy.ascontiguousarray( source )
        else:
            if contiguous and (typeCode is None or typeCode==source.dtype.char):
                return source
            elif (contiguous and cls.ERROR_ON_COPY):
                from OpenGL import error
                raise error.CopyError(
                    """Array of type %r passed, required array of type %r""",
                    source.dtype.char, typeCode,
                )
            else:
                # We have to do astype to avoid errors about unsafe conversions
                # XXX Confirm that this will *always* create a new contiguous array
                # XXX Guard against wacky conversion types like uint to float, where
                # we really don't want to have the C-level conversion occur.
                # XXX ascontiguousarray is apparently now available in numpy!
                if cls.ERROR_ON_COPY:
                    from OpenGL import error
                    raise error.CopyError(
                        """Non-contiguous array passed""",
                        source,
                    )
                if typeCode is None:
                    typeCode = source.dtype.char
                return numpy.ascontiguousarray( source, typeCode )
try:
    numpy.array( [1], 's' )
    SHORT_TYPE = 's'
except TypeError as err:
    SHORT_TYPE = 'h'
    USHORT_TYPE = 'H'

def lookupDtype( char ):
    return numpy.zeros( (1,), dtype=char ).dtype

ARRAY_TO_GL_TYPE_MAPPING = {
    lookupDtype('d'): GL_1_1.GL_DOUBLE,
    lookupDtype('f'): GL_1_1.GL_FLOAT,
    lookupDtype('i'): GL_1_1.GL_INT,
    lookupDtype(SHORT_TYPE): GL_1_1.GL_SHORT,
    lookupDtype(USHORT_TYPE): GL_1_1.GL_UNSIGNED_SHORT,
    lookupDtype('B'): GL_1_1.GL_UNSIGNED_BYTE,
    lookupDtype('c'): GL_1_1.GL_UNSIGNED_BYTE,
    lookupDtype('b'): GL_1_1.GL_BYTE,
    lookupDtype('I'): GL_1_1.GL_UNSIGNED_INT,
    #lookupDtype('P'), GL_1_1.GL_VOID_P, # normally duplicates another type (e.g. 'I')
    None: None,
}
GL_TYPE_TO_ARRAY_MAPPING = {
    GL_1_1.GL_DOUBLE: lookupDtype('d'),
    GL_1_1.GL_FLOAT:lookupDtype('f'),
    GL_1_1.GL_INT: lookupDtype('i'),
    GL_1_1.GL_BYTE: lookupDtype('b'),
    GL_1_1.GL_SHORT: lookupDtype(SHORT_TYPE),
    GL_1_1.GL_UNSIGNED_INT: lookupDtype('I'),
    GL_1_1.GL_UNSIGNED_BYTE: lookupDtype('B'),
    GL_1_1.GL_UNSIGNED_SHORT: lookupDtype(USHORT_TYPE),
    _types.GL_VOID_P: lookupDtype('P'),
    None: None,
}
