/****************************************************************************
* MeshLab                                                           o o     *
* A versatile mesh processing toolbox                             o     o   *
*                                                                _   O  _   *
* Copyright(C) 2005                                                \/)\/    *
* Visual Computing Lab                                            /\/|      *
* ISTI - Italian National Research Council                           |      *
*                                                                    \      *
* All rights reserved.                                                      *
*                                                                           *
* This program is free software; you can redistribute it and/or modify      *
* it under the terms of the GNU General Public License as published by      *
* the Free Software Foundation; either version 2 of the License, or         *
* (at your option) any later version.                                       *
*                                                                           *
* This program is distributed in the hope that it will be useful,           *
* but WITHOUT ANY WARRANTY; without even the implied warranty of            *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
* for more details.                                                         *
*                                                                           *
****************************************************************************/
#ifndef RENDERHELPER_H
#define RENDERHELPER_H

#include <QString>
#include <QImage>
#include <QGLFramebufferObject>

#include <wrap/gl/shot.h>
#include <wrap/callback.h>

#include "floatbuffer.h"

class QGLFramebufferObject;

class RenderHelper {

 public:

  GLuint vbo, nbo, cbo, ibo;  // vertex buffer object (vertices, normals, colors, indices)

  GLint programs[6];

  enum RenderingMode {FLAT=0, NORMAL=1, COLOR=2};
  RenderingMode rendmode;

  //buffers for rendered images
  unsigned char *render;
  unsigned char *color;
  unsigned char *normal;
  floatbuffer   *depth;

  // min and max for normalization purposes (e.g. weighting)
  float mindepth;
  float maxdepth;

  RenderHelper();
  ~RenderHelper();

  // init
  int initializeGL(vcg::CallBackPos *cb);
  int initializeMeshBuffers(MeshModel *mesh, vcg::CallBackPos *cb);

  // draw & readback
  void renderScene(const Shotm& view, MeshModel *mesh, RenderingMode mode, MLPluginGLContext* plugcontext, float camNear = 0, float camFar = 0);

 private:

  GLuint createShaderFromFiles(QString basename); // converted into shader/basename.vert .frag
  GLuint createShaders(const char *vert, const char *frag);

};

//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------

namespace ShaderUtils
{

  const char *importShaders(const char *filename)
  {
      FILE *fp;
      char *text = NULL;

      fp = fopen(filename, "rt");

      if (fp != NULL)
      {
          fseek(fp, 0, SEEK_END);
          size_t count = ftell(fp);
          fseek(fp, 0, 0);

          if (count > 0)
          {
              text = new char[count+1];
              count = fread(text, sizeof(char), count, fp);
              text[count] = '\0';
          }

          fclose(fp);
      }

      return text;
  }

  // Compile shader and provide verbose output
  void compileShader(GLuint shader)
  {
      static char shlog[2048];
      GLint status;
      int length;

      glCompileShader(shader);
      glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
      if (status != GL_TRUE)
      {
          glGetShaderInfoLog(shader, 2048, &length, shlog);
          std::cout << std::endl;
          std::cout << shlog << std::endl;
      }
    //else
    //  std::cout << " OK!" << std::endl;
  }

  // Link shader program and provide verbose output
  void linkShaderProgram(GLuint program)
  {
      static char proglog[2048];
      GLint status;
      int length;

      glLinkProgram(program);
      glGetProgramiv(program, GL_LINK_STATUS, &status);
      if (status != GL_TRUE)
      {
          glGetProgramInfoLog(program, 2048, &length, proglog);
          std::cout << std::endl;
          std::cout << proglog << std::endl;
      }
      //else
    //  std::cout << " OK!" << std::endl;
  }

} /* end namespace */

#endif
