// Josiah Boning
//
// project.c
// Main techlab executable

#include "project.h"
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <fftw3.h>
#include <math.h>

#define min(a,b) ((a)<(b))?(a):(b)
#define max(a,b) ((a)>(b))?(a):(b)
#define N 10000
#define ITEMS_PER_TRANS 1024

double xmin,ymin,xmax,ymax;
double *datas=NULL;
fftw_complex **trans;
int numitems=0;
int numtrans=0;
int transsize=0;
int win_wave, win_spec, win_allspec;
double tmin, tmax;

void display(void) {
	int k, n;

	/* do waveform window */
	glutSetWindow(win_wave);

	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1,1,1);

	glBegin(GL_LINES);
	glVertex3f(-1,0,0);
	glVertex3f(1,0,0);
	glVertex3f(0,-0.5,0);
	glVertex3f(0,0.5,0);
	glEnd();

	glColor3f(0.0,0.0,1.0);

	glBegin(GL_LINE_STRIP);
	for (k=0;k<numitems;k++) { 
		glVertex2f(((double)k)/numitems, ((double)datas[k])/255);
	}
	glEnd();
	glutSwapBuffers();

	/* single spectrum graph */
	glutSetWindow(win_spec);
	glClear(GL_COLOR_BUFFER_BIT);
	glBegin(GL_LINE_STRIP);
	glColor3f(1,0,0);
	n = 0;
	for (k=0; k < transsize; k++) {
		double x = ((double)k)/transsize;
		double val = pow(pow(((double)trans[n][k][0]),2)+pow(((double)trans[n][k][1]),2), 1.0/2)/(tmax-tmin);
		glColor3f(1,0,0);
		glVertex2f(((double)k)/transsize, val);
	}
	glEnd();
	glutSwapBuffers();

	/* sepctrum over time */
	glutSetWindow(win_allspec);
	glClear(GL_COLOR_BUFFER_BIT);
	glBegin(GL_POINTS);
	for (n=0; n < numtrans; n++) {
		for (k=0; k < transsize; k++) {
			double x = ((double)k)/transsize;
			double val = sqrt(pow(((double)trans[n][k][0]),2)+pow(((double)trans[n][k][1]),2))/(tmax-tmin);
			glColor3f(val*255,0,0);
			glVertex2f(((double)n)/numtrans, ((double)k)/transsize);
		}
	}
	glEnd();
	glutSwapBuffers();
}

void showGraph(void) {
	glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);

	glutInitWindowSize(400,300);
	glutInitWindowPosition(100,50);
	win_wave = glutCreateWindow("Waveform");
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-0.1,1.1,-0.6,0.6,1.0,10.0);
	gluLookAt(0.0,0.0,5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

	glutInitWindowPosition(500,50);
	glutInitWindowSize(numtrans,300);
	win_allspec = glutCreateWindow("All Frequency Spectrums");
	glClearColor(0.0,1.0,0.0,0.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-0.0,1.0,-0.0,1.0,1.0,10.0);
	gluLookAt(0.0,0.0,5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

	glutInitWindowPosition(500+numtrans,50);
	glutInitWindowSize(400,300);
	win_spec = glutCreateWindow("Single Frequency Spectrum");
	glClearColor(1.0,1.0,1.0,0.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-0.1,1.1,-1.1,1.1,1.0,10.0);
	gluLookAt(0.0,0.0,5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

	glutDisplayFunc(display);
	glutMainLoop();
}

int main(int argc,char* argv[]) {  
	//glutInit(&argc,argv);

	tmin=xmin=ymin=inf;
	tmax=xmax=ymax=-inf;

	if (argc < 2) {
		printf("You must specify a WAV file!\n");
		exit(0);
	}

	numitems = input(argv[1], &datas);
	numtrans = numitems/ITEMS_PER_TRANS;
	transsize = ITEMS_PER_TRANS/2 + 1;
	trans = transforms(datas, numitems);

	int i, j;
	for (i=0; i<numtrans; i++) {
		for (j=0; j<transsize; j++) {
			double mag = sqrt(pow((double)trans[i][j][0],2)+pow((double)trans[i][j][1],2));
			if (mag > tmax) {
				tmax = mag;
			}
			else if (mag < tmin) {
				tmin = mag;
			}
		}
	}

	printf("number of sample points: %i\n\n", numitems);

	//net* network = create_network(5, 5, 1);
	//double array[5];
	//for (i=0; i < 5; i++) {
	//	array[i] = 10;
	//}
	//process_inputs(network, array);

	//printf("%i %i\n", sizeof(neuron), sizeof(edge));
	
	//net* network = create_network(20, 20 * 2, 1);
	//process_inputs(network, datas);
	//double out = get_output(network, 0);
	//printf("out: %f\n", out);

	double frac_var = variation(datas, numitems);
	printf("Variation method: %f\n\n", frac_var);

	double frac_anam = anam(datas, numitems);
	printf("ANAM method: %f\n\n", frac_anam);

	//showGraph();

	fftw_free(datas);
	//fftw_free(trans);

	exit(0);
}
