# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (c) 2015, Vispy Development Team. All Rights Reserved.
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
# -----------------------------------------------------------------------------


"""
Implementation of a GL Program object. 

This class parses the source code to obtain the names and types of
uniforms, attributes, varyings and constants. This information is used
to provide the user with a natural way to set variables.

Gloo vs GLIR
------------

Done in this class:
  * Check the data shape given for uniforms and attributes
  * Convert uniform data to array of the correct type
  * Check whether any variables are set that are not present in source code

Done by GLIR:
  * Check whether a set uniform/attribute is not active (a warning is given)
  * Check whether anactive attribute or uniform is not set (a warning is given)


"""

import re
import numpy as np

from .globject import GLObject
from .buffer import VertexBuffer, IndexBuffer, DataBuffer
from .texture import BaseTexture, Texture2D, Texture3D, Texture1D
from ..util import logger
from .util import check_enum 
from ..ext.six import string_types
from .context import get_current_canvas
from .preprocessor import preprocess


# ----------------------------------------------------------- Program class ---
class Program(GLObject):
    """ Shader program object

    A Program is an object to which shaders can be attached and linked to
    create the final program.
    
    Uniforms and attributes can be set using indexing: e.g.
    ``program['a_pos'] = pos_data`` and ``program['u_color'] = (1, 0, 0)``.
    
    Parameters
    ----------
    vert : str
        The vertex shader to be used by this program
    frag : str
        The fragment shader to be used by this program
    count : int (optional)
        The program will prepare a structured vertex buffer of count
        vertices. All attributes set using ``prog['attr'] = X`` will
        be combined into a structured vbo with interleaved elements, which
        is more efficient than having one vbo per attribute.
    
    Notes
    -----
    If several shaders are specified, only one can contain the main
    function. OpenGL ES 2.0 does not support a list of shaders.
    """
    
    _GLIR_TYPE = 'Program'
    
    _gtypes = {  # DTYPE, NUMEL
        'float':        (np.float32, 1),
        'vec2':         (np.float32, 2),
        'vec3':         (np.float32, 3),
        'vec4':         (np.float32, 4),
        'int':          (np.int32,   1),
        'ivec2':        (np.int32,   2),
        'ivec3':        (np.int32,   3),
        'ivec4':        (np.int32,   4),
        'bool':         (np.bool,    1),
        'bvec2':        (np.bool,    2),
        'bvec3':        (np.bool,    3),
        'bvec4':        (np.bool,    4),
        'mat2':         (np.float32, 4),
        'mat3':         (np.float32, 9),
        'mat4':         (np.float32, 16),
        'sampler1D':    (np.uint32, 1),
        'sampler2D':    (np.uint32, 1),