//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  This file contains the definition of the CShaderProgram class and   //
//  its derived classes.                                                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
#include <GL/glew.h>
#include <fstream>
#include <iostream>
#include <string>
using std::ifstream;
using std::cout;
using std::endl;
using std::string;

#include "popassert.hpp"
#include "CShaderProgram.hpp"
#include "CShaderProgram2_0.hpp"
#include "CShaderProgramARB.hpp"
#include "CShaderProgramStub.hpp"


bool CShaderProgram::s_isGlewInitialized = false;




//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  Class    : CShaderProgram                                           //
//                                                                      //
//  Function : getInstance() (static)                                   //
//                                                                      //
//  Comments : This function returns an instance a shader program       //
//             handler that uses OpenGL 2.0 API or                      //
//             GL_ARB_vertex_program and GL_ARB_fragment_program        //
//             extensions depending on what is supported.               //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
CShaderProgram* CShaderProgram::getInstance()
{
  GLint returnValue = glewInit();
  if (returnValue != GLEW_OK)
    return NULL;
  else if (CShaderProgramStub::isSupported())
    return new CShaderProgramStub();
  else if (CShaderProgram2_0::isSupported())
    return new CShaderProgram2_0();
  else if (CShaderProgramARB::isSupported())
    return new CShaderProgramARB();
  else
    return NULL;
}




//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  Class    : CShaderProgram                                           //
//                                                                      //
//  Function : addShaderFile()                                          //
//                                                                      //
//  Comments : This function compiles the shader contained in the file  //
//             which name is passed as a string, and adds it to this    //
//             shader program.                                          //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
bool CShaderProgram::addShaderFile(EShaderType shaderType,
                                   const string& fileName)
{
  ifstream in(fileName.c_str());

  if (in.fail()) {
    POP_DEBUG("Error opening file \"" << fileName << "\"");
    return false;
  }

  string shaderString;

  char c = in.get();
  while (!in.eof()) {
    shaderString.push_back(c);
    c = in.get();
  }

  in.close();

  return addShader(shaderType, shaderString);
}




//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  Class    : CShaderProgram                                           //
//                                                                      //
//  Function : CShaderProgram() (default constructor)                   //
//                                                                      //
//  Comments :                                                          //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
CShaderProgram::CShaderProgram()
{
}




//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  Class    : CShaderProgram                                           //
//                                                                      //
//  Function : ~CShaderProgram() (destructor)                           //
//                                                                      //
//  Comments :                                                          //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
CShaderProgram::~CShaderProgram()
{
}
