#include <GL/glew.h> /*<- for gl...ARB extentions.  You *must* call glewInit after glutCreateWindow! */
#include <iostream>
#include <stdio.h>
#include <stdlib.h> /* for "exit" */
#include <fstream>

#include "glsl.h"

// Print an error and exit if this object had a compile error.
void checkShaderOp(GLhandleARB obj,int errtype,const char *where) 
{
        GLint compiled;
        glGetObjectParameterivARB(obj,errtype,&compiled);
        if (!compiled) {
                printf("Compile error on program: %s\n",where);
                enum {logSize=10000};
                char log[logSize]; int len=0;
                glGetInfoLogARB(obj, logSize,&len,log);
                printf("Error Log: \n%s\n",log); exit(1);
        }
}
// Create a vertex or fragment shader from this code.
GLhandleARB makeShaderObject(int target,const char *code)
{
	GLhandleARB h=glCreateShaderObjectARB(target);
	glShaderSourceARB(h,1,&code,NULL);
	glCompileShaderARB(h);
	checkShaderOp(h,GL_OBJECT_COMPILE_STATUS_ARB,code);
	return h;
}
// Create a complete shader object from these chunks of GLSL shader code.
//  You still need to glUseProgramObjectARB(return value);
//  THIS IS THE FUNCTION YOU PROBABLY *DO* WANT TO CALL!!!!  RIGHT HERE!!!!
GLhandleARB makeProgramObject(const char *vertex,const char *fragment)
{
	if (glUseProgramObjectARB==0) 
	{ /* glew never set up, or OpenGL is too old.. */
		std::cout<<"Error!  OpenGL hardware or software too old--no GLSL!\n";
		exit(1);
	}
	GLhandleARB p=glCreateProgramObjectARB();
	GLhandleARB vo=makeShaderObject(GL_VERTEX_SHADER_ARB,vertex);
	GLhandleARB fo=makeShaderObject(GL_FRAGMENT_SHADER_ARB,fragment);
	glAttachObjectARB(p,vo);
	glAttachObjectARB(p,fo);
	glLinkProgramARB(p);
	checkShaderOp(p,GL_OBJECT_LINK_STATUS_ARB,"link");
	glDeleteObjectARB(vo); glDeleteObjectARB(fo); 
	return p;
}
// Read an entire file into a C++ string.
std::string readFileIntoString(const char *fName) {
	char c; std::string ret;
	std::ifstream f(fName);
	if (!f) {ret="Cannot open file ";ret+=fName; return ret;}
	while (f.read(&c,1)) ret+=c;
        return ret;
}
// Create a complete shader object from these GLSL files.
GLhandleARB makeProgramObjectFromFiles(const char *vFile,
	const char *fFile)
{
	return makeProgramObject(
		readFileIntoString(vFile).c_str(),
		readFileIntoString(fFile).c_str()
	);
}
