#include <string.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include "../headers/GeBranchShader.h"
#include "../headers/Settings.h"

std::stack<int> GeBranchShader::shaderStack;

GeBranchShader::GeBranchShader(char* filenameVertexShader, char* filenameFragementShader) {
	shaderProgram = 0;
	createShaderProgramm(filenameVertexShader, filenameFragementShader);
	setLight(-1);
}

GeBranchShader::~GeBranchShader() {
}

void GeBranchShader::createShaderProgramm(char* filenameVertexShader, char* filenameFragementShader) {

	char *vs,*fs;
	GLuint f,v;

	v = glCreateShader(GL_VERTEX_SHADER);
	f = glCreateShader(GL_FRAGMENT_SHADER);	
	vs = textFileRead(filenameVertexShader);
	fs = textFileRead(filenameFragementShader);

	const char * vv = vs;
	const char * ff = fs;

	glShaderSource(v, 1, &vv,NULL);
	glShaderSource(f, 1, &ff,NULL);

	free(vs);free(fs);

	glCompileShader(v);
	glCompileShader(f);

	shaderProgram = glCreateProgram();
	
	glAttachShader(shaderProgram,v);
	glAttachShader(shaderProgram,f);

	glLinkProgram(shaderProgram);

	uniform_lightno = glGetUniformLocation(shaderProgram, "lightNumber");
}

void GeBranchShader::setLight(int lightNumber) { // 0-7 => light index, -1 => all lights, -2 or anything else => no light
	lightId = lightNumber;
}

char* GeBranchShader::textFileRead(char *fn) 
{
    FILE *fp;
    char *content = NULL;

    int f, count;
	
    f = open(fn, O_RDONLY);

    count = lseek(f, 0, SEEK_END);

    close(f);

    if (fn != NULL) {
        fp = fopen(fn, "r");

        if (fp != NULL) {
            if (count > 0) {
                content = (char *)malloc(sizeof(char) * (count+1));
                count = fread(content,sizeof(char),count,fp);
                content[count] = '\0';
            }
            fclose(fp);
        }
    }
    return content;
}    

void GeBranchShader::renderSingle() {
	if(settings.flags & FLAG_USE_CUSTOM_SHADER) {
		glUseProgram(shaderProgram);
		shaderStack.push(shaderProgram);
		
		glUniform1i(uniform_lightno, lightId);		
		/*const GLubyte *errString;
		GLenum errCode;		
		errCode = glGetError();
		errString = gluErrorString(errCode);*/
	}
}

void GeBranchShader::postRender() {
	if(settings.flags & FLAG_USE_CUSTOM_SHADER) {
		shaderStack.pop();
		if (shaderStack.empty()) {
			glUseProgram(0);
		}
		else {
			glUseProgram(shaderStack.top());
		}
	}
}
