
#include "Angel.h"
#include <fstream>
#include <string>
using std::string;

namespace Angel {



void complain (const string s) {
	std::cerr << s;
}

// Create a NULL-terminated string by reading the provided file
/*static char*
readShaderSource(const char* shaderFile)
{
    FILE* fp = fopen(shaderFile, "r");

    if ( fp == NULL ) { return NULL; }

    fseek(fp, 0L, SEEK_END);
    long size = ftell(fp);

    fseek(fp, 0L, SEEK_SET);
    char* buf = new char[size + 1];
    fread(buf, 1, size, fp);

	size_t temp = strlen(shaderFile);
    buf[size] = '\0';
    fclose(fp);

    return buf;
}*/

static char * readShaderSource(const string shaderFile)
{
	// size_t length;
	std::string shaderText;

	const char *CshaderFile = shaderFile.c_str();
	std::ifstream shaderStream(CshaderFile, std::iostream::in);

	if(shaderStream.is_open())
	{
		std::string line = "";
		while(getline(shaderStream, line))
		{
			shaderText += line + "\n";
		}
		shaderStream.close();
	}

	const char * temp = shaderText.c_str();
	char * returnString = new char[shaderText.length() + 1];
	strcpy(returnString, temp);


	return returnString;
}


// Create a GLSL program object from vertex and fragment shader files
GLuint
InitShader(const string vShaderFile, const string fShaderFile)
{
    struct Shader {
	string  filename;
	GLenum       type;
	const GLchar*      source;
    }  shaders[2] = {
	{ vShaderFile, GL_VERTEX_SHADER, NULL },
	{ fShaderFile, GL_FRAGMENT_SHADER, NULL }
    };

	char* logMsg;

	complain ("vShaderFile is ");
	complain (vShaderFile);
	complain ("\nfShaderFile is ");
	complain (fShaderFile);
	complain ("\n");

    GLuint program = glCreateProgram();
	
	complain ("Created program!\n");
    
    for ( int i = 0; i < 2; ++i ) {
	Shader& s = shaders[i];
	s.source = readShaderSource( s.filename );
	complain ("Shader source is\n");
	complain (s.source);
	complain ("That was the shader source.\n");
	if ( shaders[i].source == NULL ) {
	    complain ("Failed to read ");
		complain (s.filename);
		complain ("\n");
	    exit( EXIT_FAILURE );
	}

	complain ("Read a shader!\n");

	GLuint shader = glCreateShader( s.type );
	glShaderSource( shader, 1, (const GLchar**) &s.source, NULL );

	glCompileShader( shader );

	GLint  compiled;
	glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
	if ( !compiled ) {
	    complain (s.filename);
		complain (" failed to compile:");
	    GLint  logSize;
	    glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logSize );
	    /* char* */ logMsg = new char[logSize];
	    glGetShaderInfoLog( shader, logSize, NULL, logMsg );
	    complain (logMsg);
	    delete [] logMsg;

	    exit( EXIT_FAILURE );
	}

	complain ("Compiled a shader!");

	delete [] s.source;

	glAttachShader( program, shader );
    }

    /* link  and error check */
    glLinkProgram(program);

    GLint  linked;
    glGetProgramiv( program, GL_LINK_STATUS, &linked );
    if ( !linked ) {
	complain ("Shader program failed to link");
	GLint  logSize;
	glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logSize);
	/* char* */ logMsg = new char[logSize];
	glGetProgramInfoLog( program, logSize, NULL, logMsg );
	complain (logMsg);
	delete [] logMsg;

	exit( EXIT_FAILURE );
    }

    /* use program object */
    glUseProgram(program);

    return program;
}

}  // Close namespace Angel block
