#include <time.h>
#include "tga.h"

#define NUM_SPRITES 32

typedef struct
 {
  float xPos,yPos,Rotate;
  int Width,Height,Tex;
  float xVec,yVec,rVec;
 }SpriteInfo;

// Function declarations
bool LoadTexture(char *TexName, GLuint TexHandle);


void Render(void)
 {
  GLuint Texture[128];         // Handles to our textures
  SpriteInfo Spr[NUM_SPRITES]; // Sprite array
  int index,zPos,zMod;         // Loop vars
  float tX,tY,tSize;           // Temp vars to cut down on calculation
  bool ABlendFlag=TRUE,ATestFlag=FALSE,ZOrder=TRUE; // Option flags

  // Allocate all textures in one go
  glGenTextures(128,Texture);


  // Setup our screen
  glViewport(0,0,800,600);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0,800,0,600,-100,100);
  glMatrixMode(GL_MODELVIEW);
  glClearColor(0.0f,0.0f,0.0f,1.0f);

  // Enable z-buffer
  glEnable(GL_DEPTH_TEST);
  glDepthMask(TRUE);

  // Load the textures
  LoadTexture("Logo.tga",Texture[0]);
  LoadTexture("ColWheel.tga",Texture[1]);
  LoadTexture("labels.tga",Texture[2]);

  // Seed the randomiser
  srand(time(NULL));

  // Init the sprite objects
   for(index=0;index<NUM_SPRITES;++index)
    {
     Spr[index].xPos=(rand()%700)+50;
     Spr[index].yPos=(rand()%500)+50;
     tSize=rand()%256;
     Spr[index].Width=tSize;
     Spr[index].Height=tSize;
     Spr[index].xVec=(rand()%10)/10.0f;
     Spr[index].yVec=(rand()%10)/10.0f;
     Spr[index].Rotate=0;
     Spr[index].rVec=((rand()%100)/100.0f)-0.5f;
     Spr[index].Tex=rand()%2;
    }

  // Set the general polygon properties
  glColor4f(1.0f,1.0f,1.0f,1.0f);
  glEnable(GL_TEXTURE_2D);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  glAlphaFunc(GL_GREATER,0.1f);

  // This loop will run until Esc is pressed
   while(RunLevel)
    {
      if(Keys[27]) // Esc Key
       RunLevel=0;

      if(Keys[49]) // '1' Key toggles Alpha blending
       {
        ABlendFlag^=TRUE;
        Keys[49]=FALSE;
       }

      if(Keys[50]) // '2' Key toggles Alpha testing
       {
        ATestFlag^=TRUE;
        Keys[50]=FALSE;
       }

      if(Keys[51]) // '3' Key toggles z ordering
       {
        ZOrder^=TRUE;
        Keys[51]=FALSE;
       }

      // Update the sprite object positions
      for(index=0;index<NUM_SPRITES;++index)
       {
        Spr[index].xPos+=Spr[index].xVec;
         if(Spr[index].xPos < 0 || Spr[index].xPos > 800)
          Spr[index].xVec*=-1.0f;

        Spr[index].yPos+=Spr[index].yVec;
         if(Spr[index].yPos < 0 || Spr[index].yPos > 600)
          Spr[index].yVec*=-1.0f;

        Spr[index].Rotate+=Spr[index].rVec;
       }

     // Start the scene
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glLoadIdentity(); 

     // Draw status panel
     glBindTexture(GL_TEXTURE_2D,Texture[2]);
     glBegin(GL_QUADS);
      glTexCoord2f(0.0f,1.0f); glVertex3i(  0,-32,-100);
      glTexCoord2f(0.0f,0.0f); glVertex3i(  0, 96,-100);
      glTexCoord2f(1.0f,0.0f); glVertex3i(256, 96,-100);
      glTexCoord2f(1.0f,1.0f); glVertex3i(256,-32,-100);
     glEnd();

     // Set and mark options
      if(ABlendFlag)
       {
        glEnable(GL_BLEND);
        glBegin(GL_QUADS);
         glTexCoord2f(0.0f,1.0f);      glVertex3i(202, 70,-99);
         glTexCoord2f(0.0f,0.8125f);   glVertex3i(202,102,-99);
         glTexCoord2f(0.093f,0.8125f); glVertex3i(236,102,-99);
         glTexCoord2f(0.093f,1.0f);    glVertex3i(236, 70,-99);
        glEnd();
       }
      else
       {
        glDisable(GL_BLEND);
        glBegin(GL_QUADS);
         glTexCoord2f(0.093f,1.0f);    glVertex3i(202, 64,-99);
         glTexCoord2f(0.093f,0.8125f); glVertex3i(202, 96,-99);
         glTexCoord2f(0.186f,0.8125f); glVertex3i(236, 96,-99);
         glTexCoord2f(0.186f,1.0f);    glVertex3i(236, 64,-99);
        glEnd();
       }

      if(ATestFlag)
       {
        glEnable(GL_ALPHA_TEST);
        glBegin(GL_QUADS);
         glTexCoord2f(0.0f,1.0f);      glVertex3i(202, 38,-99);
         glTexCoord2f(0.0f,0.8125f);   glVertex3i(202, 70,-99);
         glTexCoord2f(0.093f,0.8125f); glVertex3i(236, 70,-99);
         glTexCoord2f(0.093f,1.0f);    glVertex3i(236, 38,-99);
        glEnd();
       }
      else
       {
        glDisable(GL_ALPHA_TEST);
        glBegin(GL_QUADS);
         glTexCoord2f(0.093f,1.0f);    glVertex3i(202, 32,-99);
         glTexCoord2f(0.093f,0.8125f); glVertex3i(202, 64,-99);
         glTexCoord2f(0.186f,0.8125f); glVertex3i(236, 64,-99);
         glTexCoord2f(0.186f,1.0f);    glVertex3i(236, 32,-99);
        glEnd();
       }

      if(ZOrder)
       {
        zMod=1;
        glBegin(GL_QUADS);
         glTexCoord2f(0.0f,1.0f);      glVertex3i(202,  6,-99);
         glTexCoord2f(0.0f,0.8125f);   glVertex3i(202, 38,-99);
         glTexCoord2f(0.093f,0.8125f); glVertex3i(236, 38,-99);
         glTexCoord2f(0.093f,1.0f);    glVertex3i(236,  6,-99);
        glEnd();
       }
      else
       {
        zMod=-1;
        glBegin(GL_QUADS);
         glTexCoord2f(0.093f,1.0f);    glVertex3i(202,  0,-99);
         glTexCoord2f(0.093f,0.8125f); glVertex3i(202, 32,-99);
         glTexCoord2f(0.186f,0.8125f); glVertex3i(236, 32,-99);
         glTexCoord2f(0.186f,1.0f);    glVertex3i(236,  0,-99);
        glEnd();
       }


     // Draw the sprites
      for(index=0,zPos=0;index<NUM_SPRITES;++index,zPos+=zMod)
       {
        tX=Spr[index].Width/2.0f;
        tY=Spr[index].Height/2.0f;

        glBindTexture(GL_TEXTURE_2D,Texture[Spr[index].Tex]);
  
        glPushMatrix();

         glTranslatef(Spr[index].xPos,Spr[index].yPos,0.0f);
         glRotatef(Spr[index].Rotate,0.0f,0.0f,1.0f);

         glBegin(GL_QUADS);
          glTexCoord2f(0.0f,0.0f); glVertex3i(-tX, tY,zPos);
          glTexCoord2f(0.0f,1.0f); glVertex3i(-tX,-tY,zPos);
          glTexCoord2f(1.0f,1.0f); glVertex3i( tX,-tY,zPos);
          glTexCoord2f(1.0f,0.0f); glVertex3i( tX, tY,zPos);
         glEnd();

        glPopMatrix();

       }

     // Show our scene
     SwapBuffers(GLDC);
    }

  // Clean up textures
  glDeleteTextures(128,Texture);
 }


// Load a TGA texture
bool LoadTexture(char *TexName, GLuint TexHandle)
 {
  TGAImg Img;        // Image loader

  // Load our Texture
   if(Img.Load(TexName)!=IMG_OK)
    return false;

  glBindTexture(GL_TEXTURE_2D,TexHandle); // Set our Tex handle as current

  // Create the texture
   if(Img.GetBPP()==24)
    glTexImage2D(GL_TEXTURE_2D,0,3,Img.GetWidth(),Img.GetHeight(),0,GL_RGB,GL_UNSIGNED_BYTE,Img.GetImg());
   else if(Img.GetBPP()==32)
    glTexImage2D(GL_TEXTURE_2D,0,4,Img.GetWidth(),Img.GetHeight(),0,GL_RGBA,GL_UNSIGNED_BYTE,Img.GetImg());
   else
    return false;

  // Specify filtering and edge actions
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);

  return true;
 }