/***************************************************************************
 *   Copyright (C) 2007 by A.J. Tavakoli                                   *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   This program is distributed in the hope that it will be useful,       *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifndef VIDEO_H
#define VIDEO_H

#include "Frustum.h"

#define WINDOW_WIDTH  1024
#define WINDOW_HEIGHT 768
#define BPP           32
#define APP_TITLE     "FPSDemo"

#define MAX_LIGHTS    4


class Video {
public:
  class Vertex {
  public:
    Math3D::Point3<float> pos;
    Math3D::Vector3<float> faceTangent;
    Math3D::Vector3<float> faceNormal;
    Math3D::Vector3<float> vertNormal;
    float tc[2];
    //float lightMapTC[2];
  };

  class Light {
  public:
    Light() {
      for ( int i=0; i < 3; i++ ) {
        ambient[i]  = 0.0f; 
        diffuse[i]  = 0.0f;
        specular[i] = 0.0f;
        pos[i]      = 0.0f;
      }

      constAtt = ambient[3] = diffuse[3] = specular[3] = pos[3] = 1.0f;
      linearAtt = quadAtt = 0.0f;
    }

    float ambient[4];
    float diffuse[4];
    float specular[4];
    float pos[4];
    float constAtt;
    float linearAtt;
    float quadAtt;
  };
  
  class Material {
  public:
    Material();

    float ambient[4];
    float diffuse[4];
    float specular[4];
    float shininess;
  };

  static void initVideo();
  static void shutdownVideo();
  static void resize(int w, int h);

  static void clearBackBuffer();
  static void clearZBuffer();
  static void showBackBuffer();

  static int loadTexture(const char *filename,
                         bool normalMap=false,
                         bool useMipMaps=true);
  static void deleteTexture(int texID);
  static void useTexture(int texID);
  static void useNormalMap(int texID);

  static void setModelTranslation(float *trans);
  static void setModelTranslation(const Point3 &trans);
  static void setModelRotation(const Quat &q);
  static void setViewTranslation(float *trans);
  static void setViewTranslation(const Point3 &trans);
  static void setViewRotation(const Quat &q);
  static void applyTransforms();

  static void setLight(int lightIndex, const Light &l);
  static void toggleLight(int lightIndex, bool on);
  static void setupLights();

  static void setMaterial(const Material &mat);

  static void renderTris(const Vertex *verts, int numTris);
  static void renderIndexedTris(const Vertex *verts, 
                                const unsigned int *indices,
                                int numTris);
  static void renderQuads(const Vertex *verts, int numQuads);

  static void disableNormalMapping();
  static void enableNormalMapping();
  static void disableTextures();
  static void enableTextures();

  inline static bool getNormalMappingEnabled() { return normalMappingEnabled; }
  inline static bool getTexturesEnabled()      { return texturesEnabled;      }
  inline static bool getShadersSupported()     { return shadersSupported;     }

  static Frustum getFrustum();

  // utility methods
  static void computeTangentAndNormal(Vertex &v1, Vertex &v2, Vertex &v3);

private:
  static void checkGLError();
  static bool initShaders();
  static void setGLMatrices();

  static bool shadersSupported;
  static bool normalMappingEnabled;
  static bool texturesEnabled;

  static int normalMapShader;

  static float modelTranslation[3],
               modelRotation[16],
               viewTranslation[3],
               viewRotation[16];

  static bool  lightEnabled[MAX_LIGHTS];
  static Light lights[MAX_LIGHTS];
};


#endif
