/*
 * (C) Copyright Ian D. Romanick 2007
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * on the rights to use, copy, modify, merge, publish, distribute, sub
 * license, and/or sell copies of the Software, and to permit persons to whom
 * the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
 * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif

#include <GL/gl.h>
#include <GL/glext.h>
#include <string.h>


class glsl_uniform {
public:
    glsl_uniform(void)
    {
        next = NULL;
        handle = -1;
        name = NULL;
    }


    ~glsl_uniform(void)
    {
        delete name;
    }


    glsl_uniform *next;
    GLint handle;
    char *name;
};


class glsl_shader_program {
public:
    glsl_shader_program(GLhandleARB p, char *n)
    {
        uniforms = NULL;
        program = p;
	
	const size_t len = strlen(n);

	name = new char[len + 1];
	(void) memcpy(name, n, len);
	name[len] = '\0';
    }
    
    ~glsl_shader_program(void);

    void activate();

    void uniform(const char *name, float x);
    void uniform(const char *name, float x, float y);
    void uniform(const char *name, float x, float y, float z);
    void uniform(const char *name, float x, float y, float z, float w);

    void uniform2(const char *name, unsigned count, const float *v);
    void uniform3(const char *name, unsigned count, const float *v);
    void uniform4(const char *name, unsigned count, const float *v);

    void uniform_matrix4(const char *name, unsigned count, bool transpose,
			 const float *v);

    void uniform(const char *name, int x);
    
    int get_info_log(char *log_buffer, size_t size);
    void print_log(bool only_if_error, const char *file, int line);
    
    const char *get_name(void)
    {
	return name;
    }

private:
    glsl_uniform *add_uniform(const char *name);
    glsl_uniform *find_uniform(const char *name);

    glsl_uniform *uniforms;

    GLhandleARB program;

    char *name;
};
