#include "stdafx.h"

#include <stdlib.h>

#include <windows.h> // win headers;
#include "glut.h" // this one includes the upper two headers;

#include <iostream>
using namespace std;

#include <math.h>

/*
#include <GL/glut.h>
*/

//
// zoom counter
//
int pix_zoom = 1;

//
// mouse click coordinates;
//
int click_x = 0;
int click_y = 0;

//
// initial circle radus;
//
int circle_radius = 64;

//
// color index table;
//
int color_index = 0;
int color_table[7][3] = {

		{255, 0, 0},
		{0, 255, 0},
		{0, 0, 255},
		{255, 255, 0},
		{0, 255, 255},
		{255, 0, 255},
		{255, 255, 255}

};

//
// initial "screen" parameters;
//
#define ScreenWidth 640
#define ScreenHeight 480
GLubyte screen[ScreenHeight][ScreenWidth][3];

//
// initial win parameters;
//
int win_width = ScreenWidth;
int win_height = ScreenHeight;

void plot(int x, int y) {

	if (x < 0 || x > ScreenWidth) return;
	if (y < 0 || y > ScreenHeight) return;

	screen[y][x][0] = color_table[color_index][0];
	screen[y][x][1] = color_table[color_index][1];
	screen[y][x][2] = color_table[color_index][2];

}

void bresenham_circle(int sx, int sy, int r) {

	int j=0;

        if (r >= ScreenWidth/2) return;

        int d = 2*(1-r);
        int x = 0;
        int y = r;

        do {

                plot(sx+x,sy+y);
                plot(sx+x,sy-y);
                plot(sx-x,sy+y);
                plot(sx-x,sy-y);

                if (d < -y) { // Hi

                        x++;
                        d += (2*x + 1);

                } else if (d > x) { // Vi

                        y--;
                        d += (-2*y + 1);

                } else { // Di

                        x++;
                        y--;
                        d += ((2*x + 1) + (-2*y + 1));

                }
			j++;
        } while (y >= 0);
		cout << "calcs: " << j << endl;
}

void bresenham_circle2(int sx, int sy, int r) {

	int j=0;
	for(float i=0; i < 3.14/2; i+=0.001) {
		j++;
		int x = r*cos(i);
		int y = r*sin(i);

		plot(sx + x, sy + y);
		plot(sx - x, sy + y);
		plot(sx - x, sy - y);
		plot(sx + x, sy - y);

	}
	cout << "calcs2: " << j << endl;

}

void initView() { // what we gonna show;

	glClearColor(0, 0, 0, 0);

}

void mouse(int button, int state, int mx, int my) {

	if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {

		click_x = mx;
		click_y = win_height - my;

	} else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {

		for(int y = 0; y < ScreenHeight; y++)
			for(int x = 0; x < ScreenWidth; x++) 
				screen[y][x][0] = screen[y][x][1] = screen[y][x][2] = 0;

	}

	cout << mx << " " << win_height - my << endl;

	glutPostRedisplay();
	
}

void keyboard(unsigned char key, int x, int y)
{
	switch (key)  {
		case 27: // ESCAPE key
			cout << "escape pressed" << endl;
			exit (0);
			break;
	}
}

void keyboard2(int key, int x, int y)
{
	switch (key)  {
		case GLUT_KEY_UP :
			cout << "up key pressed" << endl;
			pix_zoom ++;
            break;
        case GLUT_KEY_DOWN:
			cout << "down key pressed" << endl;
			pix_zoom --;
			break;
        case GLUT_KEY_LEFT:
			cout << "left key pressed" << endl;
            break;
        case GLUT_KEY_RIGHT:
			color_index++; color_index %= 7;
			cout << "right key pressed" << endl;
            break;
	}

	cout << color_index << " " << pix_zoom << endl;

	glutPostRedisplay();
}

void reshape(int w, int h) { // when user moves our window; 

	glViewport(0, 0, w, h); // viewport transofrmation;

	glMatrixMode(GL_PROJECTION); // projection transformation
	glLoadIdentity();

	gluOrtho2D(0.0, w, 0.0, h);

	glMatrixMode(GL_MODELVIEW); // modelling transformation ;; ant glLookAt must be set before that;
	glLoadIdentity();

	win_height = h;
	win_width = w;

}

void display() { // our actual scene;

	glClear(GL_COLOR_BUFFER_BIT); // our color buffer 'll be cleared;

	glRasterPos2i(0, 0);

	if (click_x != 0 && click_y != 0) {

		bresenham_circle(click_x, click_y, circle_radius);
		bresenham_circle2(click_x+2*circle_radius+5, click_y, circle_radius);

		glPixelZoom(pix_zoom, pix_zoom);
		glDrawPixels(ScreenWidth, ScreenHeight, GL_RGB, GL_UNSIGNED_BYTE, screen);

	}

	glFlush();

}

int main(int argc, char *argv[]) { // our main function;

	glutInit(&argc, argv);

    glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);

    glutInitWindowSize(ScreenWidth, ScreenHeight);
    glutInitWindowPosition(100, 100);

    glutCreateWindow ("Bresenham's circle");

    initView(); // initialize our 2d view;

    glutDisplayFunc(display); 
	glutReshapeFunc(reshape);

	glutMouseFunc(mouse);
	glutKeyboardFunc(keyboard);
	glutSpecialFunc(keyboard2);
    glutMainLoop();

	return 0;

}
