#include <stdio.h>
#include <stdlib.h>
#include <gd.h>
#include "gdfonts.h"
#include "gdfontt.h"
#include "gdfontl.h"
#include "gdfontl.h"
#include "gdfontmb.h"
#include <math.h>
#include <stdint.h>
#include <string.h>

int main(int argc, char **argv){
	gdImagePtr im;
	FILE *in;
	FILE *out;
	int width = 800;
	int height = 600;
	int box_h = 10;
	int box_w = 10;
	int x1, y1, x2, y2;
	int num1 = 1;
	size_t num2 = 0;
	int num3 = 0;
	int size_max = 64;
	int size_step = 1;
	int cycle_max = 500;
	int cycle_step = 25;
	int stagger = 0;
	size_t readprev = 0;
	size_t readcur = 0;
	int step_h = 0;
	int step_v = 0;
	uint32_t read_buffer_size = 64;
	char *read_buffer = (char *)malloc(read_buffer_size + 1);
	(void)memset( (void *)read_buffer, '\0', read_buffer_size + 1);
	im = gdImageCreate(width, height);
size_t values[38] = {64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152, 65536, 98304, 131072, 196608, 262144,
                           393216, 524288, 786432, 1048576, 1572864, 2097152, 3145728, 4194304, 6291456, 8388608, 12582912, 16777216, 25165824};
	//byte_loop loop unrolled_loop rep_byte rep_4byte rep_8byte vector_loop libcall
	//int colors[8];
	int white = gdImageColorAllocate(im, 255, 255, 255);
	int black = gdImageColorAllocate(im, 0, 0, 0);
	int red = gdImageColorAllocate(im, 255, 0, 0);
	int blue = gdImageColorAllocate(im, 0, 0, 255);
        int green = gdImageColorAllocate(im, 0, 255, 0);
        int yellow = gdImageColorAllocate(im, 255, 255, 0);
        int orange = gdImageColorAllocate(im, 255, 128, 0);
        int purple = gdImageColorAllocate(im, 255, 0, 255);
        int brown = gdImageColorAllocate(im, 128, 64, 0);
        int grey = gdImageColorAllocate(im, 128, 128, 128);

	int colors[8] = {red, blue, green, yellow, orange, purple, brown, grey};

        int styleDashed[8];
        styleDashed[0] = gdTransparent;
        styleDashed[1] = black;
        styleDashed[2] = gdTransparent;
        styleDashed[3] = black;
        styleDashed[4] = gdTransparent;
        styleDashed[5] = black;
        styleDashed[6] = gdTransparent;
        styleDashed[7] = black;

        gdImageSetStyle(im, styleDashed, 8);

        char *token;
        char *line;
        char *search = " ";
	char labelstr[32];
	double tmp1 = 0;

        gdImageLine(im, 100, 10, 100, height-100, black);
        gdImageLine(im, 100, height-100, width-100, height-100, black);
        gdImageString(im, gdFontMediumBold, 5, 5, (unsigned char *)"cycles", black);
	gdImageString(im, gdFontMediumBold, width/2, height-25, (unsigned char *)"size", black);
        //gdImageString(im, gdFontMediumBold,   1530   ,  100        , "Swap Usage" , black);
        //gdImageString(im, gdFontMediumBold,   50   ,   140    , "Hours" , black);


//	x1 = width-200;
//	y1 = box_h*2;
//	x2 = width-100;
//	y2 = box_h*2+box_h;
	gdImageString(im, gdFontMediumBold, width-80, box_h, (unsigned char *)"byte_loop", black);
	gdImageFilledRectangle(im, width-100, box_h, width-90, box_h*2, red);
	gdImageString(im, gdFontMediumBold, width-80, box_h*3, (unsigned char *)"loop", black);
	gdImageFilledRectangle(im, width-100, box_h*3, width-90, box_h*4, blue);
	gdImageString(im, gdFontSmall, width-80, box_h*5, (unsigned char *)"unrolled_loop", black);
	gdImageFilledRectangle(im, width-100, box_h*5, width-90, box_h*6, green);
	gdImageString(im, gdFontMediumBold, width-80, box_h*7, (unsigned char *)"rep_byte", black);
	gdImageFilledRectangle(im, width-100, box_h*7, width-90, box_h*8, yellow);
	gdImageString(im, gdFontMediumBold, width-80, box_h*9, (unsigned char *)"rep_4byte", black);
	gdImageFilledRectangle(im, width-100, box_h*9, width-90, box_h*10, orange);
	gdImageString(im, gdFontMediumBold, width-80, box_h*11, (unsigned char *)"rep_8byte", black);
	gdImageFilledRectangle(im, width-100, box_h*11, width-90, box_h*12, purple);
	gdImageString(im, gdFontMediumBold, width-80, box_h*13, (unsigned char *)"vector_loop", black);
	gdImageFilledRectangle(im, width-100, box_h*13, width-90, box_h*14, brown);
	gdImageString(im, gdFontMediumBold, width-80, box_h*15, (unsigned char *)"libcall", black);
	gdImageFilledRectangle(im, width-100, box_h*15, width-90, box_h*16, grey);

	//num2 = (width-200)/38;
	num2 = 15;
	//num2 = (width-200)/size_max/size_step;
	//100 - 2000000000
	for(num1=0; num1<38; num1++){

		(void)sprintf(labelstr, "%zu", values[num1]);
		gdImageString(im, gdFontSmall, num2*(num1+1)+100, height-75+stagger, (unsigned char *)labelstr, black);
		gdImageLine(im, num2*(num1+1)+100, height-75+stagger, num2*(num1+1)+100, height-100, black);
		gdImageLine(im, num2*(num1+1)+100, height-100, num2*(num1+1)+100, 10, gdStyled);
		if(stagger == 25)
			stagger = 0;
		else
			stagger = 25;

		//stagger ^= 1;
	}
	//gdImageLine(im, 0, 0, width, 0, black);
	//num2 = (height-120)/cycle_max/cycle_step;
	num2 = 10;
	//26
	//19*26 = 494
	//10*48 = 480
	//5*96 = 480
	//for(num1=0; num1<cycle_max; num1+=cycle_step){
	for(num1=0; num1<10; num1++){
		//tmp1 = log(num2);

		if(num2<1000){
			(void)sprintf(labelstr, "%zu", num2);
			//num3 = num2;
		}else if(num2<1000000){
			(void)sprintf(labelstr, "%zuK", num2/1000);
			//num3 = num2/100;
		}else if(num2<1000000000){
			(void)sprintf(labelstr, "%zuM", num2/1000000);
			//num3 = num2/100000;
		}else{
			(void)sprintf(labelstr, "%zuB", num2/1000000000);
			//num3 = num2/100000000;
		}

		gdImageString(im, gdFontSmall, 50, height-100-48*num1, (unsigned char *)labelstr, black);
		gdImageLine(im, 50, height-100-48*num1, 100, height-100-48*num1, black);
		gdImageLine(im, 100, height-100-48*num1, width-100, height-100-48*num1, gdStyled);
		num2 *= 10;
	}

	//step_h = (width-200)/size_max/size_step;
	step_h = 15;
	step_v = 48;
	//ratio = 
	for(num1=1; num1<9; num1++){
		(void)sprintf(labelstr, "results/r%d.txt", num1);
		in = fopen(labelstr, "r");
		num2 = 0;
		readprev = 0;
		(void)memset( (void *)read_buffer, '\0', read_buffer_size + 1);
		while( fgets(read_buffer, read_buffer_size, in) != NULL){
			//printf("line %d\n", num2);
			if(num2 == 38)
				break;
			//tmp1 = atof(read_buffer);
			//convert readcur
			tmp1 = log(atof(read_buffer));

			tmp1 *= 48;
			tmp1 -= 192;
//printf("%lf\n", tmp1);
			//readcur = (int)tmp1;

			if(tmp1 > 480)
				tmp1 = 480;


			readcur = height-100-tmp1;
			gdImageLine(im, num2*step_h+100, height-100-readprev, (num2+1)*step_h+100, readcur, colors[num1-1]);

			num2++;
			readprev = tmp1;
		}
		
		fclose(in);
	}

	out = fopen("graph.png", "w");
	gdImageInterlace(im, 1);
	gdImagePng(im, out);
	fclose(out);
	//fclose(in);
	free(read_buffer);
	gdImageDestroy(im);



	return 0;
}
