/*  ===========================================================
					CAMERA.C
===========================================================

  DESCRIPTION

  This module provides keyframe tools for camera zoom

=========================================================== */
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h> /* openGL header - aadesche */
#include "head.h"
#include "camera.h"
#include <string.h>


static char *camkeyfile="cam.keys";	/* file name for camera keys file */

extern void jitter(GLdouble, GLdouble); //  GCK 3/11/01
extern double pixdx;  // GCK 3/11
extern double pixdy;  // GCK 3/11

double g_eyex=0.0;
double g_eyey=0.0;
double g_eyez=0.0;
double g_fovy = 40.0;
int g_camera = 1;

int g_nCamKeys;
int g_CamKeys[MAXKEYS];

int InitCamera()
{
	camkrec.eyex[0] = 0.0;
	camkrec.eyey[0] = 0.0;
	camkrec.eyez[0] = 0.0;
	camkrec.fovy[0] = 40.0;
	g_nCamKeys = 1;
	g_CamKeys[0] = 0;		

	return 0;
}

int UpdateCamera() 
{
    int w, h;

	if (g_anim && g_camera) {
		ReadCameraKey(anim_frame);
	}


	glLoadIdentity();

	
	
	/*glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
	w = (GLfloat) glutGet(GLUT_WINDOW_WIDTH);
	h = (GLfloat) glutGet(GLUT_WINDOW_HEIGHT);
	gluPerspective(g_fovy, (GLfloat) w/ (GLfloat)h, 1.0, 100.0 ) ;
	glMatrixMode( GL_MODELVIEW );*/
	jitter(pixdx,pixdy);  // GCK 3/11/01
	gluLookAt(g_eyex,g_eyey,g_eyez,0.0,0.0,-5,0.0,1.0,0.0);

	return(TRUE);
}


int ReadCameraKey(int f)
{
	int lk, hk, k;

	k = LookCameraKey(f);

	if (k>1) {
		g_eyex = camkrec.eyex[k];
		g_eyey = camkrec.eyey[k];
		g_eyez = camkrec.eyez[k];
		g_fovy = camkrec.fovy[k];
	}
	else {   /* linear interpolate the keys */

		//if (g_nCamKeys == 1) return 1;  /* only one frame, nothing to update*/

		lk = CamLowKey(f);

		hk = lk+1;

		//printf("stored key = %d, f = %d\n", g_CamKeys[lk], f);

		if (lk == g_nCamKeys-1) {
			g_eyex = camkrec.eyex[lk];
			g_eyey = camkrec.eyey[lk];
			g_eyez = camkrec.eyez[lk];
			g_fovy = camkrec.fovy[lk];
		}
		else if (f == g_CamKeys[hk]) {
			g_eyex = camkrec.eyex[hk];
			g_eyey = camkrec.eyey[hk];
			g_eyez = camkrec.eyez[hk];
			g_fovy = camkrec.fovy[hk];
		}
		else {
			g_eyex = CamLinterp(f, g_CamKeys[lk], g_CamKeys[hk], camkrec.eyex[lk], camkrec.eyex[hk]);
			g_eyey = CamLinterp(f, g_CamKeys[lk], g_CamKeys[hk], camkrec.eyey[lk], camkrec.eyey[hk]);
			g_eyez = CamLinterp(f, g_CamKeys[lk], g_CamKeys[hk], camkrec.eyez[lk], camkrec.eyez[hk]);
			g_fovy = CamLinterp(f, g_CamKeys[lk], g_CamKeys[hk], camkrec.fovy[lk], camkrec.fovy[hk]);

			//printf("%f\n", g_eyez);
		}
	}
	
	return(TRUE);
}


int WriteCameraKey(int f)
{
	int i, lk;

	if (f > g_keys[g_nkeys-1]) {
		printf("must be less or equal to number of keyframes\n");
		printf("last key frame %d, %d\n", g_nkeys, g_keys[g_nkeys-1]);
		return (FALSE);
	}

	if (f > g_CamKeys[g_nCamKeys-1]) {  /* append key at the end */
		printf("\nnum keys: %d\n", g_nCamKeys);
		printf("key larger %d > %d\n", f, g_CamKeys[g_nCamKeys]);
		camkrec.eyex[g_nCamKeys] = g_eyex;
		camkrec.eyey[g_nCamKeys] = g_eyey;
		camkrec.eyez[g_nCamKeys] = g_eyez;
		camkrec.fovy[g_nCamKeys] = g_fovy;

		g_CamKeys[g_nCamKeys] = f;
		g_nCamKeys++;
	}
	else {  /* insert key */
		lk = CamLowKey(f);
		if (f == g_CamKeys[lk]) {
			camkrec.eyex[lk] = g_eyex;
			camkrec.eyey[lk] = g_eyey;
			camkrec.eyez[lk] = g_eyez;
			camkrec.fovy[lk] = g_fovy;	

		}
		else {
		
			for (i=g_nCamKeys-1; i>lk; i--) {
				g_CamKeys[i+1] = g_CamKeys[i];
				camkrec.eyex[i+1] = camkrec.eyex[i];
				camkrec.eyey[i+1] = camkrec.eyey[i];
				camkrec.eyez[i+1] = camkrec.eyez[i];
				camkrec.fovy[i+1] = camkrec.fovy[i];
			}
			
			camkrec.eyex[lk+1] = g_eyex;
			camkrec.eyey[lk+1] = g_eyey;
			camkrec.eyez[lk+1] = g_eyez;
			camkrec.fovy[lk+1] = g_fovy;	
			g_CamKeys[lk+1] = f;
			g_nCamKeys++;
		}
		
	}
	
	for (i=0;i<g_nCamKeys; i++) printf("%f\n", camkrec.eyez[i]);
	return(TRUE);
}


int DeleteCameraKey(int f)
{
	int i, n;

	n = -1;
	for (i=0; i<g_nCamKeys; i++) {
		if (f == g_CamKeys[i]) n = i;
	}

	if (n<0) {
		printf("Frame not found\n");
		return -1;
	}

	for (i=n; i<g_nCamKeys; i++) {
		g_CamKeys[i] = g_CamKeys[i+1];
	}

	g_nCamKeys--;
	
	return (TRUE);
}


int CamLowKey(int f)
{
	int i;

	//printf("num of keys %d\n", g_nCamKeys);
	for (i=0; i<g_nCamKeys; i++) {
		//printf("%d %d\n", f, g_CamKeys[i]);
		if (f == g_CamKeys[i]) return i;
		if (f < g_CamKeys[i]) return i-1;
	}
	return g_nCamKeys-1;
}

int LookCameraKey(int f)
{
	int i;

	for (i=0; i<g_nCamKeys; i++) {
		if (f == g_CamKeys[i]) return i;
	}

	return -1;
}

double CamLinterp(int f, int f0, int f1, double v0, double v1)
{
	return  (v0 + (( (double) f - (double) f0) /  ( (double) f1 - (double) f0 )) * (v1-v0 ));

}


int ScaleCameraKeys(int nlf,int ff,int lf)
{
	int i, fk, lk, lastfnum, offset;
	double scfactor;
   
	if (g_CamKeys[g_nCamKeys-1] == 0) {		/* no keys */
		printf("No keys to scale.\n");
		return(FALSE);
	}
	fk = LookCameraKey(ff);
	lk = LookCameraKey(lf);
	if (fk == -1 ||  lk == -1) {
		printf("Not Valid key frame(s).\n");
		return(FALSE);
	}
	if ( ff >= lf) {
		printf("ff must be less than lf\n");
		return(FALSE);
	}
	if ( nlf < ff) {
		printf("nlf must be greater than ff\n");
		return(FALSE);
	}	

	/* scale the keys inbetween */
	lastfnum = ff;
	for (i=fk+1; i<=lk; i++) {
		scfactor = ((((g_CamKeys[i] - ff) * (nlf-ff)) / (lf-ff))+ff);
		printf("scale factor = %lf\n", scfactor);
		g_CamKeys[i] = (int) scfactor;
		if (g_CamKeys[i] == lastfnum) g_CamKeys[i] = g_CamKeys[i] + 1;
		lastfnum = g_CamKeys[i];		
	}

	/* copy the remaining keys */
	if (lk != g_nCamKeys-1) {
		offset = nlf - lf;
		for (i=lk+1; i<g_nCamKeys; i++) {
			g_CamKeys[i] = g_CamKeys[i] + offset;
		}
	}

	return (TRUE);

}


int SaveCameraKeys(char filename[])
{
	int i;
	FILE *fp;

	printf(filename);
	fp = fopen(filename, "wb");
	if (fp == NULL)  {
		printf("file can not be open for write\n");
		return(FALSE);
	}


	for (i=0; i < g_nCamKeys; i++) {
		printf("%d %lf %lf %lf %lf\n", i, camkrec.eyex[i], camkrec.eyey[i], camkrec.eyez[i], camkrec.fovy[i]);	
		fprintf(fp, "%d %lf %lf %lf %lf\n", g_CamKeys[i], camkrec.eyex[i], camkrec.eyey[i], camkrec.eyez[i], camkrec.fovy[i]);
	}

	fclose(fp);
	return (TRUE);
}

int LoadCameraKeys(char filename[])
{
	int i;
	FILE *fp;

	fp = fopen(filename, "rb");

	if (fp == NULL)  {
		printf("file can not be open for read\n");
		return(FALSE);
	}

	i = 0;
	while (!feof(fp)) {
		fscanf(fp, "%d %lf %lf %lf %lf\n", &g_CamKeys[i], &camkrec.eyex[i], &camkrec.eyey[i], &camkrec.eyez[i], &camkrec.fovy[i]);
		i = i+1;
	}

	g_nCamKeys = i;

	fclose(fp);
	return (TRUE);
}



int PrintCameraKeys()
{
	int i;

	printf("Existing keys: ");
	for (i=0; i<g_nCamKeys; i++) {
		printf("%d ", g_CamKeys[i]);
	}
	printf("\n");

	return(TRUE);

}


void ResetCamera()
{
	g_eyex=0.0;
	g_eyey=0.0;
	g_eyez=0.0;
	g_fovy = 40.0;

}

