//----------------------------------------------------------------------------
// High-res OpenGL snapshot example code
// (C) 1999,2004   Bill Baxter
//----------------------------------------------------------------------------
// This code fragment shows what you need to do to use 
// hiressnap.cpp and hiressnap.h for making insanely high resolution
// snapshots of your OpenGL scene.
//----------------------------------------------------------------------------
// Some parts of the code refer to the GLVU class library, which is available
// here:  http://www.cs.unc.edu/~walk/software/glvu
//----------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without
// fee, provided that the above copyright notice appear in all copies
// and that both that copyright notice and this permission notice
// appear in supporting documentation.  Binaries may be compiled with
// this software without any royalties or restrictions.
//
// The University of North Carolina at Chapel Hill makes no representations 
// about the suitability of this software for any purpose. It is provided 
// "as is" without express or implied warranty.
//-----------------------------------------------------------------------------


// INCLUDES
#include <glvu.hpp>
#include "hiressnap.h"

GLVU g_glvu;

bool g_doHiResSnap = false;
int  g_hiResGridSize = 3;
bool g_snapAlpha = false;

int g_firstTimeMainDisplay = -1;


//----------------------------------------------------------------------------
// @ mainDisplayFunc
//----------------------------------------------------------------------------
void mainDisplayFunc( )
{
  Camera cam;
    cam = *g_glvu.GetCurrentCam();

    HIRES_SNAP_BEGIN(MY_SNAP_LABEL,cam,g_hiResGridSize,g_hiResGridSize,g_snapAlpha,g_doHiResSnap);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf( cam.GetProjectionMatrix(M) );
    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixf( cam.GetModelviewMatrix(M) );

    // Draw the scene HERE
    {
      // draw draw draw...
    }

    HIRES_SNAP_END(MY_SNAP_LABEL,g_doHiResSnap);
  }

  glutSwapBuffers();
}

string getUniqueFilename(const char *pattern)
{
  FILE *fp;

  char* wild = strchr(pattern, '*');
  if (!wild) {
    wild = strchr(pattern, '?');
  }
  if (!wild) {
    string emptee;
    return emptee;
  }

  string pre(pattern, 0, wild-pattern);
  string post(pattern, wild-pattern+1,string::npos);

  // GENERATE A UNIQUE FILENAME
  char FileName[128];
  static int SnapShotNum=0;
  int UniqueFound=0;
  do {
    sprintf(FileName,"%s%03d%s",pre.c_str(), SnapShotNum, post.c_str());
    if (fp=fopen(FileName,"r")) fclose(fp);
    else UniqueFound=1;
    SnapShotNum++;
  } while(!UniqueFound);
  return string(FileName);
}

void grabSnapshot(const char *file, bool useAlpha = false)
{
  cerr << "Writing snapshot " 
       << (useAlpha?"with alpha ":"")
       << "to file " << file << "." << endl;
  unsigned char *buf = 0;
  int w, h;
  if (useAlpha) SaveColorAndAlphaBuffer(buf, w, h);
  else          SaveColorBuffer(buf, w, h);
  WriteTGA(file, buf, w, h, useAlpha?4:3);
  delete [] buf;
}



//----------------------------------------------------------------------------
// @ appKeyboardFunc
//----------------------------------------------------------------------------
void appKeyboardFunc(unsigned char key, int x, int y)
{
  switch (key) 
  {
    case 'Y':  /// TOGGLE BACKGROUND MODE
      ++g_backgroundMode %= BKGND_NUM_MODES;
      {
        switch(g_backgroundMode) {
          case BKGND_SKYBOX:
            if (g_skyImageData[5].data != 0) { break; }
            else {
              g_backgroundMode++;
              // and fall thru!!
            }            
          case BKGND_BLACK:
            glClearColor(0,0,0,0);
            break;
          case BKGND_WHITE:
            glClearColor(1,1,1,0);
            break;
          case BKGND_BLUE:
            glClearColor(0.2,0.3,0.7,0);
            break;
          default:
            cerr << "Unknown background mode!" << endl;
            break;
        }
      }
      break;
    case ';':   /// CHANGE SNAPSHOT MODE (3 or 4 CHANNEL)
      g_snapAlpha = !g_snapAlpha;
      cerr << "Snapshots will be taken in "
           << (g_snapAlpha?"4-channel RGBA":"3-channel RGB") << " format" << endl;
      break;
    case '\'':  /// TAKE A SCREEN RESOLUTION SNAPSHOT
    case '=':  /// TAKE A SCREEN RESOLUTION SNAPSHOT
      {
        string fname = getUniqueFilename("snap*.tga");
        grabSnapshot(fname.c_str(), g_snapAlpha);
      }
      break;
    case '"':  /// TAKE A HIGH RES SNAPSHOT IN N PARTS
        cerr << "Taking high resolution screenshot.  Use the following to assemble the parts:\n"
             << ">  for f in hires_*.ppm; do convert -flip $f `basename $f .ppm`.png; done\n" 
             << ">  montage -mode Concatenate -tile 3x3 hires_*.png montage.png" 
             << endl;
        g_doHiResSnap = true;
      }
      break;
    case '(':  /// DECREASE HIGH RES SNAPSHOT RESOLUTION
      if (--g_hiResGridSize < 0) g_hiResGridSize = 0;
        cerr << "High Resolution snapshot now using "
             << g_hiResGridSize << "x" << g_hiResGridSize << " grid" << endl;
      break;
    case ')':  /// INCREASE HIGH RES SNAPSHOT RESOLUTION
      g_hiResGridSize++;
      cerr << "High Resolution snapshot now using "
           << g_hiResGridSize << "x" << g_hiResGridSize << " grid" << endl;
      break;
  default:
    g_glvu.DefaultKeyboardFunc(key,x,y);
    break;
  }
}

