#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>

//#define ALGS 8
//#define MAX_SIZE 32768

//#define MAX_CLOCK 2000
//#define MAX_VOLT 2000
#define POINTS 16

float clocks[POINTS] = {852, 1000, 1200, 1300, 1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500, 1525, 1550, 1575, 1600};
float volts[POINTS] = {800, 865, 875, 875, 885, 885, 895, 920, 945, 965, 990, 1010, 1030, 1060, 1090, 1115};
//float watts[POINTS] = {57, 60, 60, 65, 68, 72, 75, 78, 82, 85, 92, 102, 117, 127, 139};

/*
struct pairs{
	int voltage;
        int clock;
};

const struct pairs Pairs[POINTS] = {{800, 852}, {865, 1000}, {875, 1200}, {875, 1300}, {885, 1325}, {885, 1350}, {895, 1375}, {920, 1400}, {945, 1425}, {965, 1450}, {965, 1455}, {990, 1475}, {1010, 1500}, {1030, 1525}, {1060, 1550}, {1090, 1575}, {1115, 1600}};
*/






/*
clock     set_v     load_v   peak_w     benchmarks
2.0       0.975v    0.98v    57W
2.1       1.0v      1.025v   60W
2.2       1.0v      1.025v   60W
2.3       1.05v     1.075v   65W
2.4       1.075v    1.1v     68W
2.5       1.1v      1.125v   72W
2.6       1.125v    1.16v    75W
2.7       1.15v     1.18v    78W
2.8       1.175v    1.20v    82W
2.9       1.20v     1.20v    85W
3.0       1.25v     1.27v    92W
3.1       1.30v     1.32v    102W
3.2       1.375v    1.40v    117W
3.3       1.40v     1.45v    127W
3.4       1.45v     1.49v
*/



/*
void Label_Suffix(char *labelstr, size_t num){
                if(num<1024){
                        (void)sprintf(labelstr, "%zu", num);
                }else if(num<1000000){
                        (void)sprintf(labelstr, "%zuK", num/1000);
                }else if(num<1000000000){
                        (void)sprintf(labelstr, "%zuM", num/1000000);
                }else{
                        (void)sprintf(labelstr, "%zuB", num/1000000000);
                }
}
*/

int main(int argc, char **argv){
	gdImagePtr im;
//	FILE *in;
	FILE *out;
	int width = 200;
	int height = 200;
//	int box_h = 10;
	float x1, y1, x2, y2;
	int num1 = 1;
	int num2 = 0;
	int num3 = 0;

//	int size_max = 64;
//	size_t cycle_max = 500;
	float tmp1 = 0;
	float step_c, step_v;//, biggest, smallest;
	int stagger = 0;
//	int readprev = 0;
//	int readcur = 0;
//	int step_h = 0;

//	uint32_t read_buffer_size = 256;
//	char *read_buffer = (char *)malloc(read_buffer_size + 1);
//	(void)memset( (void *)read_buffer, '\0', read_buffer_size + 1);
//	size_t data[ALGS][MAX_SIZE];
	//im = gdImageCreate(width, height);
	//byte_loop loop unrolled_loop rep_byte rep_4byte rep_8byte vector_loop libcall
	//int colors[8];

	int white, black, red, blue, green, yellow, orange, purple, brown, grey;
//	int colors[8];
	int styleDashed[8];
	char labelstr[32];

	//determine width/height and max volt/clock
	//for(num1=0; num1<POINTS; num1++){
	//	if(clocks[num1] 
	//}
	step_c = clocks[POINTS-1] - clocks[0];
	step_v = volts[POINTS-1] - volts[0];
	width += step_c;
	height += step_v;
	step_c /= 10;
	step_v /= 10;
	step_c = step_c;
	step_v = step_v;

	im = gdImageCreate(width, height);
	white = gdImageColorAllocate(im, 255, 255, 255);
	black = gdImageColorAllocate(im, 0, 0, 0);
	red = gdImageColorAllocate(im, 255, 0, 0);
	blue = gdImageColorAllocate(im, 0, 0, 255);
	green = gdImageColorAllocate(im, 0, 255, 0);
	yellow = gdImageColorAllocate(im, 255, 255, 0);
	orange = gdImageColorAllocate(im, 255, 128, 0);
	purple = gdImageColorAllocate(im, 255, 0, 255);
	brown = gdImageColorAllocate(im, 128, 64, 0);
	grey = gdImageColorAllocate(im, 128, 128, 128);

/*
	colors[0] = red;
	colors[1] = blue;
	colors[2] = green;
	colors[3] = yellow;
	colors[4] = orange;
	colors[5] = purple;
	colors[6] = brown;
	colors[7] = grey;
*/

	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);

        gdImageLine(im, 100, 100, 100, height-100, black);
        gdImageLine(im, 100, height-100, width-100, height-100, black);
	gdImageLine(im, width-100, 100, width-100, height-100, black);

        gdImageString(im, gdFontMediumBold, 5, 5, (unsigned char *)"volts", green);
	gdImageString(im, gdFontMediumBold, width/2, height-25, (unsigned char *)"clock", black);
//	gdImageString(im, gdFontMediumBold, width-80, 5, (unsigned char *)"watts", red);

	//horizontal labels
	//num2 = (width-200)/10;
	//num2 = step_c;
	//num3 = 0;
	tmp1 = clocks[0];
	for(num1=0; num1<11; num1++){
		//(void)sprintf(labelstr, "%uMHz", (unsigned int)clocks[num1]);
		(void)sprintf(labelstr, "%uMHz", (unsigned int)(clocks[0]+step_c*num1));
		gdImageString(im, gdFontSmall, (int)(step_c*num1+100), height-75+stagger, (unsigned char *)labelstr, black);
		gdImageLine(im, (int)(step_c*num1+100), height-75+stagger, (int)(step_c*num1+100), height-100, black);
		gdImageLine(im, (int)(step_c*num1+100), height-100, (int)(step_c*num1+100), 100, gdStyled);

		if(stagger == 25)
			stagger = 0;
		else
			stagger = 25;
		//num3++;
		//tmp1 += step_c;
	}

/*
biggest = 0;
smallest = 100000000;
for(num1=0; num1<POINTS; num1++){
if(volts[num1] > biggest)
biggest = volts[num1];
if(volts[num1] < smallest)
smallest = volts[num1];
}
step = biggest - smallest;
step /= 20;
*/

	//left vertical labels for voltage
	//num3 = (height - 200)/11;
	//num2 = 0;
	//num3 = step_v;
	//tmp1 = volts[0];
	for(num1=0; num1<11; num1++){
		tmp1 = volts[0]+step_v*num1;
		(void)sprintf(labelstr, "%.03f", tmp1/1000);
		gdImageString(im, gdFontSmall, 50, height-100-(int)(step_v*num1), (unsigned char *)labelstr, green);
		gdImageLine(im, 50, height-100-(int)(step_v*num1), 100, height-100-(int)(step_v*num1), black);
		gdImageLine(im, 100, height-100-(int)(step_v*num1), width-100, height-100-(int)(step_v*num1), gdStyled);
		//num2++;
		//tmp1 += step_v;
	}


	//right vertical labels for watts
	//num2 = 0;
	//num3 = (height - 200)/11;
/*
biggest = 0;
smallest = 100000000;
for(num1=0; num1<POINTS; num1++){
if(watts[num1] > biggest)
biggest = watts[num1];
if(watts[num1] < smallest)
smallest = watts[num1];
}
step = biggest - smallest;
step /= 20;
*/
/*
	tmp1 = 0;
	for(num1=0; num1<10; num1++){
		(void)sprintf(labelstr, "%.03f%%", tmp1);
		gdImageString(im, gdFontSmall, width-80, height-100-num3*num2, (unsigned char *)labelstr, red);
		gdImageLine(im, width-80, height-100-num3*num2, width-100, height-100-num3*num2, black);
		//gdImageLine(im, 100, height-100-num3*num2, width-100, height-100-num3*num2, gdStyled);
		num2++;
		tmp1 += 10;
	}
*/

	//draw voltage line
//	num2 = (width-200)/11;
//	num3 = (height - 200)/20;
/*
biggest = 0;
smallest = 100000000;
for(num1=0; num1<POINTS; num1++){
if(volts[num1] > biggest)
biggest = volts[num1];
if(volts[num1] < smallest)
smallest = volts[num1];
}
step = biggest - smallest;
step /= 20;
*/
/*
	x1 = 100;
	tmp1 = volts[0]/volts[POINTS-1];
	tmp1 *= height - 200;
	y1 = height-100;
	y1 -= tmp1;
	for(num1=1; num1<POINTS; num1++){
		//tmp1 = volts[num1] - volts[0];
		//tmp1 /= step;
//		tmp1 = 1 - volts[0]/volts[num1];
		tmp1 = volts[num1]/volts[POINTS-1]; //volts[POINTS-1];
		tmp1 *= height - 200;
		y2 = height-100;
		y2 -= tmp1;
		x2 = x1+num2;
		gdImageLine(im, (int)x1, (int)y1, (int)x2, (int)y2, green);
		x1 = x2;
		y1 = y2;
	}
*/
//stagger = 0;
//(void)sprintf(labelstr, "%uMHz", (unsigned int)clocks[0]);
//gdImageString(im, gdFontSmall, num2*(num3)+100, height-75+stagger, (unsigned char *)labelstr, black);
//gdImageLine(im, num2*(num3)+100, height-75+stagger, num2*(num3)+100, height-100, black);
//gdImageLine(im, num2*(num3)+100, height-100, num2*(num3)+100, 100, gdStyled);

	x1 = 100;
	y1 = height-100;
	for(num1=1; num1<POINTS; num1++){
		x2 = 100+(clocks[num1]-clocks[0]);
		y2 = height-100-(volts[num1]-volts[0]);
		gdImageLine(im, (int)x1, (int)y1, (int)x2, (int)y2, green);
		x1 = x2;
		y1 = y2;
	}

	//draw wattage line
	//num2 = (width-200)/POINTS;
//	num3 = (height - 200)/20;
/*
biggest = 0;
smallest = 100000000;
for(num1=0; num1<POINTS; num1++){
if(watts[num1] > biggest)
biggest = watts[num1];
if(watts[num1] < smallest)
smallest = watts[num1];
}
step = biggest - smallest;
step /= 20;
*/
/*
	x1 = 100;
	y1 = height-100;
	for(num1=1; num1<POINTS; num1++){
		//tmp1 = watts[num1] - smallest;
		//tmp1 /= step;
		tmp1 = 1 - watts[0]/watts[num1];
		tmp1 *= height - 200;
		y2 = height-100;
		y2 -= tmp1;
		x2 = x1+num2;
		gdImageLine(im, (int)x1, (int)y1, (int)x2, (int)y2, red);
		x1 = x2;
		y1 = y2;
	}
*/



//	gdImageLine(im, (int)x1, (int)y1, (int)x2, (int)y2, colors[num1]);

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

	return 0;
}
