#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include  <sys/types.h>
#include <dirent.h>
#include "cores.h"
#include "processes.h"
#include "cpuinfo.h"
#include "frequency.h"
#include "meminfo.h"
#include "netinfo.h"

//int maxtextbuffer = sizeof(char)*250;
//#define SIZE sizeof(char)*250
#define SIZE 255

int count, count2, count3;
char *cpu = "cpu";
char *mem = "mem";
char *net = "net";

double cpuarray1[3][64][10];
double minutearray[61][64][9];
double minutearray2[64][9];
double walltime[61];
double tenminutearray[64][9][10];

int memarray1[9];
int memarray2[60][9];
int memtenarray2[10][9];

double netarray1[2][9];
double netarray2[4];

int pid;

void title() {
        printf("\tlsnet is a product of the linuxsociety team\n");
        printf("\tThis is version 0.3.0-dev dated 02/24/2009\n");
        printf("\n");
return;  
}

void usage() {
        printf("Usage: lsnet -[option]\n");
        printf("Options:\n");
        printf("        -h: display this help menu\n");  
        printf("        -a: run all monitors\n");
        printf("        -1: run cpu monitor\n");
        printf("        -2: run mem monitor\n");
        printf("        -3: run net monitor\n");
        printf("\n");           
}

 //runall(cores, cpufrequency, cpuarray1, minutearray, minutearray2, walltime, tenminutearray, memfrequency, memarray1, memarray2, memtenarray2, netfrequency, netarray1, netarray2);
 


int runall(int cores, int cpufrequency, double cpuarray1[3][64][10], double minutearray[61][64][9], double minutearray2[64][9], double walltime[61], double tenminutearray[64][9][10], 
	int memfrequency, int memarray1[9], int memarray2[60][9], int memtenarray2[10][9], int netfrequency, double netarray1[2][9], double netarray2[4]) 
{
        title();

	pid = fork();
	if (pid == 0) 
        	cputenminute(cores, cpufrequency, cpuarray1, minutearray, minutearray2, walltime, tenminutearray);
     	else 
        	pid = fork();
		if (pid == 0)
			memtenminute(memfrequency, memarray1, memarray2, memtenarray2);
		else
			pid = fork();
			if (pid == 0)
				netenminute(netfrequency, netarray1, netarray2);
			else

	//tenminute(cores, cpufrequency, cpuarray1, minutearray, minutearray2, walltime);
        //int processes2 = processes();
        printf( "\n\tMonitor daemons started.\t\n");

        return 0;  
}



int main(int argc, char **argv) {
        int cpufrequency = frequency(cpu);
        //cpufrequency = atoi(cpufrequency);
	int memfrequency = frequency(mem);
	//memfrequency = atoi(memfrequency);
        int netfrequency = frequency(net);
        //netfrequency = atoi(netfrequency);

        int cores = coresdetected();
        int count4;
        int o;
        while((o=getopt(argc, argv, "ha123")) != EOF) {
                switch(o) {
                        case 'h':
                                usage();
                                exit(1);
                                break;
                        case 'a':
				runall(cores, cpufrequency, cpuarray1, minutearray, minutearray2, walltime, tenminutearray, memfrequency, memarray1, memarray2, memtenarray2, netfrequency, netarray1, netarray2);
				//printf("\n\n\tRuntime error!\n");
                                
                                exit(1);
                                break;
                        case '1':
                                title();
			        pid = fork();
				if (pid == 0)
                			cputenminute(cores, cpufrequency, cpuarray1, minutearray, minutearray2, walltime, tenminutearray);
        			else
                                printf("\n\n\tCpu Daemon Started.\n");
                                exit(1);
                                break;
                        case '2':
                                title();
				pid = fork();
				if (pid == 0)
					memtenminute(memfrequency, memarray1, memarray2, memtenarray2);
				else
                                printf("\n\n\tMem Daemon Started.\n");
                                exit(1);
                                break;
                        case '3':
                                title();
				pid = fork();
				if (pid == 0)
					netenminute(netfrequency, netarray1, netarray2);
				else 
                                printf("\n\n\tNet Daemon Started.\n");
                                exit(1);
                                break;
                       default:
                                break;   
                        }
        }
        while(optind) {
                title();
                usage();
                printf("\nError: No run options specified!\n\n");
                exit(1);
        }
return 0;
}
                                

int memtenminute(int memfrequency, int memarray1[9], int memarray2[60][9], int memtenarray2[10][9]){
	struct tm *local;
	time_t t;

	char *token;
	char *line;
	char *search = "X";

	int i,whatever,count1,count2;
	local = localtime(&t);

        char singlentrystr[20];
	char datestr[30];
	char bigstr[ ( (10 * sizeof(datestr)) + (10 * sizeof(singlentrystr) ) + 11) * 10 ];
        int emptyvarstr;

	int var1 = 0; 
	int var2 = 0;
        FILE* fp;
	int poll = 60 / memfrequency;
	while (1 == 1)
	{	
		//memset( (void *) minutearray2, '\0', sizeof(double) * 64 * 9);
		//memset ((void*) memarray2, '\0', sizeof (memarray2) * 9);
		memset ((void*) memtenarray2, '\0', sizeof (memtenarray2));
		memset ((void*) bigstr, '\0', sizeof (bigstr));
		for(i = 1; i <= 10; i++)
		{
			memset ((void*) singlentrystr, '\0', sizeof (singlentrystr));
			memset ((void*) datestr, '\0', sizeof (datestr));
			memoneminute(memfrequency, memarray1, memarray2);
			//printf("finished min %d\n", i);
			t = time(NULL);
			local = localtime(&t);
                        strcat(datestr, asctime(local));
			datestr[strlen(datestr)-1]='\0';

			strcat (bigstr, datestr);
			strcat (bigstr, " ");
			//printf("datestr: %s\n", datestr);
			for (count1 = 1; count1 <= poll; count1++)
			{
				//printf("memarray2 %d %d: %d\n",count1, count2, memarray2[count1][5] );

				var1 = 0;
				var2 = 0;
				var1 = memarray2[count1][5];
				var2 = memtenarray2[i][5];
				//printf("var1: %d\n", var1 );
				//printf("var2: %d\n", var2);
				for (count2 = 1; count2 <= 8; count2++)
				{
					//printf("memarray2 %d %d: %d\n",count1, count2, memarray2[count1][count2] );
					if (var1 > var2)
						memtenarray2[i][count2] = memarray2[count1][count2];
						//printf("wrote: %d\n", memtenarray2[i][count2]); 
						//only save the polling interval variables with the highest memused instance
				
				}
			

			}

			//printf("out of 3 loops!\n");
			for (count2 = 1; count2 <= 8; count2++)
			{	// add variables onto date
				if (count2 != 1)
				{
					emptyvarstr = sprintf( singlentrystr, " %d", memtenarray2[i][count2]);
				}else{
					emptyvarstr = sprintf( singlentrystr, "%d", memtenarray2[i][count2]);
					//printf("memtenarray: %d\n",memtenarray2[i][count2]);
					//printf("singlentrystr: %s\n",singlentrystr);
				}
				strcat (bigstr, singlentrystr);
				//memset ((void*) singlentrystr, '\0', sizeof (singlentrystr));
			}
			//add an X to the end of bullshit for splitting later
			if (i != 10)
			{
				strcat (bigstr, "X");
			}
			//printf("bigstr: %s\n", bigstr);
			//memset ((void*) memarray2, '\0', sizeof (memarray2));
		}
			//printf("finished 10min\n");

		//int memtotal, memfree, buffers, cached, memused, swaptotal, swapfree, swapused;
		//Sun Feb 22 22:20:13 2009 2026.77 379.44 713.68 238.45 1647.33 10722.93 10563.75 159.18
	
		if (fp = fopen("/usr/lib/lsnet/lsmem.log", "a"))
		{
			//line = bullshit;
			token = strtok(bigstr, search);
			for (count1 = 1; count1 <= 10; count1++)
			{
				//line = bullshit;
				//token = strtok(line, search);
				fprintf(fp, "%s\n", token );
				token = strtok(NULL, search);
				//fprintf(fp, "%s\n", token );
				//token = strtok(NULL, search);
				//fprintf(fp, "%s\n", token );
			}



		}

		fclose( fp );
	}

	return 0;
}




int cputenminute(int cores, int cpufrequency, double cpuarray1[2][4][8], double minutearray[61][64][9], double minutearray2[64][9], double walltime[61], double tenminutearray[64][9][10]) 
{
	struct tm *local;
	time_t t;
	int i,whatever,count2,count3;
	local = localtime(&t);

        char processtr[(sizeof(double) + 1)];
	int processnum;
	char singlentrystr[sizeof(double) + 1];
	char onemincpustr[((10*cores*8)+cores)];
	char datestr[( (sizeof(char) * 30) + sizeof(processtr) + sizeof(onemincpustr) + 2)];
	char bigstr[((10 * sizeof(datestr)) + 10)];

        int emptyreturnvar;
        char *token;
        char *line;
        char *search = "X";



	//printf("bullshit: %d\n", cpufrequency);
	FILE* fp;
	while (1 == 1)
	{
			memset ((void*) bigstr, '\0', sizeof (bigstr));
			memset ((void*) datestr, '\0', sizeof (datestr));
        		for(i = 1; i <= 10; i++)
        		{
				memset ((void*) processtr, '\0', sizeof (processtr));
				memset ((void*) onemincpustr, '\0', sizeof (onemincpustr));
				memset ((void*) datestr, '\0', sizeof (datestr));
				//memset ((void*) whatever2, '\0', sizeof (whatever2));
				cpuoneminute(cores, cpufrequency, cpuarray1, minutearray, minutearray2, walltime);
				t = time(NULL);
				//local = localtime(&t);
				//local = gmtime(&t);
				local = localtime(&t);
				strcat(datestr, asctime(local));
				datestr[strlen(datestr)-1]='\0';
				processnum = processes();
				//printf ("processes: %d\n", processnum);
				//exit (1);
				emptyreturnvar = sprintf( processtr, "%d", processnum);
				//strcat(datestr, processstr);
				//printf("\nProcesstr: %s\n", processtr);
				strcat(datestr, " ");
				strcat(datestr, processtr);
				strcat(datestr, " ");
                		for (count2 = 1; count2 <= cores; count2++)
                		{
					if(count2 != 1){
						strcat(onemincpustr, "+");
        				}
                        		for (count3 = 1; count3 < 8; count3++)
                        		{   
						if(count3 == 1){
							emptyreturnvar = sprintf( singlentrystr, "%lf", minutearray2[count2][count3]);
						}else{
                                		emptyreturnvar = sprintf( singlentrystr, " %lf", minutearray2[count2][count3]);
						}
        					strcat(onemincpustr, singlentrystr);
                        		}
					//strcat(onemincpustr, "+");
				}
				//printf("completed first minute: %s\n", );
				//strcat(datestr, processtr);
				//strcat(datestr, " ");
				strcat(datestr, onemincpustr);
				strcat(bigstr, datestr);
				if (i != 10){
					strcat(bigstr, "X");
				}
					
				//printf("completed minute %d: %s\n", i, bigstr);
				//printf("sizeof whatever2: %d\n", sizeof(whatever2));
			}
			//printf("completed 10 minutes: %s\n", bigstr);

        	if (fp = fopen("/usr/lib/lsnet/lscpu.log", "a"))
        	{

			token = strtok(bigstr, search);
			for (i = 1; i <= 10; i++)
			{
				fprintf(fp, "%s\n",token ); 
				if (i != 10)
				{
					token = strtok(NULL, search);
				}
			}
		}
		fclose( fp );
		//memset ((void*) bigstring, '\0', sizeof (bigstring));
		//memset ((void*) bullshit4, '\0', sizeof (bullshit4));
	}
	return 0;
}

//double minutearray[61][64][9];
//double minutearray2[64][9];

int netenminute(int netfrequency, double netarray1[2][9], double netarray2[4])
{
        //printf("inside netenminute\n");
        struct tm *local;
        time_t t;
        int i,count1,count2,emptyreturnvar;
        local = localtime(&t);
        char singlentrystr[(sizeof(double) + 2)];
	char oneminnetstr[(sizeof(double)*4) + 2];
	char datestr[(30 + sizeof(oneminnetstr))];
	char bigstr[((10 * sizeof(datestr)) + 10)];
	//printf("inside netenminute 2\n");
        char *token;
        char *line;
        char *search = "X";

        FILE* fp;
        while (1 == 1)
        {
			memset ((void*) bigstr, '\0', sizeof (bigstr));
                        for(i = 1; i <= 10; i++)
                        {
				//memset( (void *) oneminnetstr, '\0', sizeof(double) * 64 * 9);
                                memset ((void*) oneminnetstr, '\0', sizeof (oneminnetstr));
                                memset ((void*) datestr, '\0', sizeof (datestr));
				//printf("inside netenminute 3\n");
				netoneminute(netfrequency, netarray1, netarray2, walltime);                                
                                t = time(NULL);
                                local = localtime(&t);
                                strcat(datestr, asctime(local));
                                datestr[strlen(datestr)-1]='\0';
				strcat(datestr, " ");
                                for (count1 = 1; count1 < 5; count1++)
                                {
         	                       if(count1 == 1){
                 	                      emptyreturnvar = sprintf( singlentrystr, "%lf", netarray2[count1]);
                                       }else{
                        	              emptyreturnvar = sprintf( singlentrystr, " %lf", netarray2[count1]);
                                       }
                                       strcat(oneminnetstr, singlentrystr);
                                }
				strcat(datestr, oneminnetstr);
				strcat(bigstr, datestr);
                                if(i != 10){
                                        strcat(bigstr, "X");
                                } 
				//strcat(bigstr, );
				//printf("bigstr: %s\n", bigstr);			

			}

                if (fp = fopen("/usr/lib/lsnet/lsnet.log", "a"))
                {
 
                        token = strtok(bigstr, search);
                        for (i = 1; i <= 10; i++)
                        {
                                fprintf(fp, "%s\n",token );
                                if (i != 10)
                                {
                                        token = strtok(NULL, search);
                                }
                        }
                }
                fclose( fp );
	}
	return 0;

}


int cpuoneminute(int cores, int cpufrequency, double cpuarray1[2][4][8], double minutearray[61][64][9], double minutearray2[64][9], double walltime[61]) {
	//printf("cores: %d cpufrequency: %d inside onminute\n", cores, cpufrequency);
        int user, nice, system, idle, iowait, irq, softirq, totalcycles;
	int count1, count2, count3;
	int poll = 60 / cpufrequency;
	//int minutearray[poll][cores][8];
	//int minutearray2[cores][8];
	//double walltime[poll]; 
	double walltimetotal = 0;
	//minutearray[0][0][0] = 0;
	//memset ((void*) minutearray, '\0', sizeof (minutearray));
	for (count1 = 1; count1 <= poll; count1++)
	{
		double te0 = cpuinfo(cores, cpufrequency, cpuarray1);
		//double cpuarray1[2][cores][8] = cpuinfo(cores, cpufrequency);
		for (count2 = 1; count2 <= cores; count2++)
		{
			
                        //for (count3 = 1; count3 < 8; count3++)
                        //{
                                //total cpu cycles used per core/run
                          //      minutearray[count1][count2][8] = minutearray[count1][count2][8] + cpuarray1[2][count2][count3];
				//runtime between reads
				

                        //}

				//poll cpu variable	 //run two minus run one, cycles for those variables
                	minutearray[count1][count2][1] = (cpuarray1[2][count2][1] - cpuarray1[1][count2][1]);
        		minutearray[count1][count2][2] = (cpuarray1[2][count2][2] - cpuarray1[1][count2][2]);
        		minutearray[count1][count2][3] = (cpuarray1[2][count2][3] - cpuarray1[1][count2][3]);  
        		minutearray[count1][count2][4] = (cpuarray1[2][count2][4] - cpuarray1[1][count2][4]);
        		minutearray[count1][count2][5] = (cpuarray1[2][count2][5] - cpuarray1[1][count2][5]);
        		minutearray[count1][count2][6] = (cpuarray1[2][count2][6] - cpuarray1[1][count2][6]);
        		minutearray[count1][count2][7] = (cpuarray1[2][count2][7] - cpuarray1[1][count2][7]);
			minutearray[count1][count2][8] = 0;
			for (count3 = 1; count3 < 8; count3++)
			{
				//total cpu cycles used per core/run
				minutearray[count1][count2][8] = (minutearray[count1][count2][8] + minutearray[count1][count2][count3]); 
			}
			//translate cycles into percentage use
                        minutearray[count1][count2][1] = ((minutearray[count1][count2][1] / minutearray[count1][count2][8]) * 100);
                        minutearray[count1][count2][2] = ((minutearray[count1][count2][2] / minutearray[count1][count2][8]) * 100);
                        minutearray[count1][count2][3] = ((minutearray[count1][count2][3] / minutearray[count1][count2][8]) * 100);
                        minutearray[count1][count2][4] = ((minutearray[count1][count2][4] / minutearray[count1][count2][8]) * 100);
                        minutearray[count1][count2][5] = ((minutearray[count1][count2][5] / minutearray[count1][count2][8]) * 100);
                        minutearray[count1][count2][6] = ((minutearray[count1][count2][6] / minutearray[count1][count2][8]) * 100);
                        minutearray[count1][count2][7] = ((minutearray[count1][count2][7] / minutearray[count1][count2][8]) * 100);
                        //walltime[poll] = 

			
		}
		//the runtime between reads for that polling
		walltime[poll] = te0;
		//that total 
		walltimetotal = walltimetotal + te0;
	}
	// determine average percentage use for given minute, weighted average taking into account walltime of each polling
	//memset(minutearray2, 0, 9);
	//memset ((void*) minutearray2, '\0', sizeof (minutearray2));
	memset( (void *) minutearray2, '\0', sizeof(double) * 64 * 9);
        for (count1 = 1; count1 <= poll; count1++)
        {

		for (count2 = 1; count2 <= cores; count2++)
                {

			for (count3 = 1; count3 < 8; count3++)
                        {
				//minutearray2[count2][count3] = minutearray2[count2][count3] + (minutearray[count1][count2][count3] * (walltime[poll]/ walltimetotal));
				minutearray2[count2][count3] = (minutearray2[count2][count3] + (minutearray[count1][count2][count3] * (walltime[poll]/ walltimetotal)));
			}

		}

	}
	return 0;
}


int memoneminute(int memfrequency, int memarray1[9], int memarray2[60][9])
{
	int poll = 60 / memfrequency;
	//printf("In memoneminute poll: %d\n", poll);
	int count1; 
	int count2;
	memset ((void*) memarray2, '\0', sizeof (memarray2));
	for (count1 = 1; count1 <= poll; count1++)
	{
		//memset ((void*) memarray2, '\0', sizeof (memarray2));
		//memset ((void*) memarray1, '\0', sizeof (memarray1));
		meminfo(memfrequency, memarray1);

		//printf("In memoneminute poll: %d\n", poll);
		//printf("Finished run %d of meminfo\n", firstcounter);

		for (count2 = 1; count2 <= 8; count2++)
		{
			memarray2[count1][count2] = memarray1[count2];
			//printf("In memoneminute memarray1 %d: %d\n", count2, memarray1[count2] );
			//printf("writen to memarray2 %d %d: %d\n",count1, count2, memarray2[count1][count2] );
		}

	}
	//printf("returning to memtenmin\n");
	return 0;
}

//netoneminute(netfrequency, netarray1, netarray2, walltime);

int netoneminute(int netfrequency, double netarray1[2][9], double netarray2[4])
{
	//printf("NETFREQUENCY: %d\n", netfrequency);
        int poll = 60 / netfrequency;
	double walltime1; 
	//double walltimesum = 0; 
        int count1 = 1; 
	int count2 = 1;
	//printf("inside netoneminute\n");



	walltime1 = 0;
	memset ((void*) netarray2, '\0', sizeof (netarray2));
        for (count1 = 1; count1 <= poll; count1++)
        {
		//sum of the walltimes
		walltime1 = walltime1 + netinfo(netfrequency, netarray1);
		for (count2 = 1; count2 <= 4; count2++)
		{	
			//sum of the results
			netarray2[count2] = netarray2[count2] + netarray1[1][count2];				
		}
		
	}
	
	for (count2 = 1; count2 <= 4; count2++)
	{	
		//results per total time  in kb/s pack/s
		netarray2[count2] = netarray2[count2] / walltime1;
	}

	//printf("oneminarray Total Netin: %lf\n", netarray2[1]);
	//printf("oneminarray total packin: %lf\n", netarray2[2]);  
	//printf("oneminarray Total Netout: %lf\n", netarray2[3]);
	//printf("oneminarray total packout: %lf\n", netarray2[4]);

	return 0;
}
