#include <iostream>
#include <sstream>
#include <SDL/SDL.h>

#include "gl.hpp"

using namespace std;

// --- GL_VERSION_1_3 ---
//PFNGLACTIVETEXTUREPROC glActiveTexture;

// --- GL_VERSION_2_0 ---
PFNGLATTACHSHADERPROC glAttachShader;
PFNGLCOMPILESHADERPROC glCompileShader;
PFNGLCREATEPROGRAMPROC glCreateProgram;
PFNGLCREATESHADERPROC glCreateShader;
PFNGLGETSHADERIVPROC glGetShaderiv;
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
PFNGLLINKPROGRAMPROC glLinkProgram;
PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLUSEPROGRAMPROC glUseProgram;
PFNGLUNIFORM1FPROC glUniform1f;
PFNGLUNIFORM1IPROC glUniform1i;
PFNGLUNIFORM3FVPROC glUniform3fv;

//------------------------------------------------------------------------------
bool InitGL()
//------------------------------------------------------------------------------
{
  int ver[2];
  char c;

  const char *strGL = reinterpret_cast<const char *>(glGetString(GL_VERSION));
  cout << "OpenGL verzió: " << strGL << " (szükséges: 3.0)" << endl << flush;
  istringstream ss(strGL);
  ss >> ver[0];
  if (ver[0] < 3)
    return false;

  const char *strGLSL = reinterpret_cast<const char *>(glGetString(GL_SHADING_LANGUAGE_VERSION));
  cout << "GLSL verzió: " << strGLSL << " (szükséges: 1.30)" << endl << flush;
  ss.str(strGLSL);
  ss >> ver[0] >> c >> ver[1];
  if ((ver[0] == 1) && (ver[1] < 30))
    return false;

  bool result = true;

//  if (!(glActiveTexture      = (PFNGLACTIVETEXTUREPROC     )(SDL_GL_GetProcAddress("glActiveTexture")))) result = false;
  if (!(glAttachShader       = (PFNGLATTACHSHADERPROC)(SDL_GL_GetProcAddress("glAttachShader")))) result = false;
  if (!(glCompileShader      = (PFNGLCOMPILESHADERPROC)(SDL_GL_GetProcAddress("glCompileShader")))) result = false;
  if (!(glCreateProgram      = (PFNGLCREATEPROGRAMPROC)(SDL_GL_GetProcAddress("glCreateProgram")))) result = false;
  if (!(glCreateShader       = (PFNGLCREATESHADERPROC)(SDL_GL_GetProcAddress("glCreateShader")))) result = false;
  if (!(glGetShaderiv        = (PFNGLGETSHADERIVPROC)(SDL_GL_GetProcAddress("glGetShaderiv")))) result = false;
  if (!(glGetShaderInfoLog   = (PFNGLGETSHADERINFOLOGPROC)(SDL_GL_GetProcAddress("glGetShaderInfoLog")))) result = false;
  if (!(glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)(SDL_GL_GetProcAddress("glGetUniformLocation")))) result = false;
  if (!(glLinkProgram        = (PFNGLLINKPROGRAMPROC)(SDL_GL_GetProcAddress("glLinkProgram")))) result = false;
  if (!(glShaderSource       = (PFNGLSHADERSOURCEPROC)(SDL_GL_GetProcAddress("glShaderSource")))) result = false;
  if (!(glUseProgram         = (PFNGLUSEPROGRAMPROC)(SDL_GL_GetProcAddress("glUseProgram")))) result = false;
  if (!(glUniform1f          = (PFNGLUNIFORM1FPROC)(SDL_GL_GetProcAddress("glUniform1f")))) result = false;
  if (!(glUniform1i          = (PFNGLUNIFORM1IPROC)(SDL_GL_GetProcAddress("glUniform1i")))) result = false;
  if (!(glUniform3fv         = (PFNGLUNIFORM3FVPROC)(SDL_GL_GetProcAddress("glUniform3fv")))) result = false;

  cout << "OpenGL kiterjesztések:" << endl;
//  cout << " - glActiveTexture: " << (glActiveTexture ? "van" : "nincs") << endl;
  cout << " - glAttachShader: " << (glAttachShader ? "van" : "nincs") << endl;
  cout << " - glCompileShader: " << (glCompileShader ? "van" : "nincs") << endl;
  cout << " - glCreateProgram: " << (glCreateProgram ? "van" : "nincs") << endl;
  cout << " - glCreateShader: " << (glCreateShader ? "van" : "nincs") << endl;
  cout << " - glGetShaderiv: " << (glGetShaderiv ? "van" : "nincs") << endl;
  cout << " - glGetShaderInfoLog: " << (glGetShaderInfoLog ? "van" : "nincs") << endl;
  cout << " - glGetUniformLocation: " << (glGetUniformLocation ? "van" : "nincs") << endl;
  cout << " - glLinkProgram: " << (glLinkProgram ? "van" : "nincs") << endl;
  cout << " - glShaderSource: " << (glShaderSource ? "van" : "nincs") << endl;
  cout << " - glUseProgram: " << (glUseProgram ? "van" : "nincs") << endl;
  cout << " - glUniform1f: " << (glUniform1f ? "van" : "nincs") << endl;
  cout << " - glUniform1i: " << (glUniform1i ? "van" : "nincs") << endl;
  cout << " - glUniform3fv: " << (glUniform3fv ? "van" : "nincs") << endl;
  cout << " " << (result ? "sikeres" : "sikertelen") << endl;
  cout << flush;

  return result;
}
