#include <stdio.h>
#include <stdlib.h>

#define ROWS 500
#define COLS 500

typedef struct pixel{
	int r,g,b;
} Color;

Color image [ROWS][COLS];

void ensure(int val, char* message)
{
	if (!val){
		printf("%s\n", message);
		exit(0);
	}
}

void display (void)
{
	FILE* disp;
	disp = popen("display -", "w");
	fprintf(disp, "P3\n%d %d\n255\n", ROWS, COLS);
	int r, c;
	for ( r=0; r<ROWS; r++ )
	{
		for ( c=0; c<COLS; c++ )
		{
			fprintf(disp, "%d %d %d ", image[r][c].r, image[r][c].g, image[r][c].b);
		}
		fprintf(disp, "\n");
	}
	pclose(disp);
}

void wash(Color wash_color){
	int r, c;
	for (r=0; r<ROWS; r++){
		for (c=0; c<COLS; c++){
			image[r][c] = wash_color;
	}}
}

void plot(int x, int y, Color c){
	image[y][x] = c;
}

void line(int x0, int y0, int x1, int y1, Color c){
	int tmp;
	
	// check bounds
	ensure(x0 <= COLS && x1 <= COLS && y0 <= ROWS && y1 <= ROWS, "Line: Out of bounds");

	// Vertical
	if (x0 == x1)
	{
		if (y0 > y1)
		{
			tmp = y0;
			y0 = y1;
			y1 = tmp;
		}
		do{
			plot(x0, y0, c);
			y0++;
		} while (y0 <= y1);
		return;
	}

	// Always draw right to left
	if (x0 > x1)
	{
		tmp = x0;
		x0 = x1;
		x1 = tmp;
		tmp = y0;
		y0 = y1;
		y1 = tmp;
	}
	
	int dx = x1 - x0;
	int dy = y1 - y0;
	int err = 0;
		
	if (dy > 0) { // DOWN
		if (dy > dx){ // DOWN
			do{
				if (err >= dy)
				{
					err -= dy;
					x0++;
				}
				plot(x0, y0, c);
				y0++;
				err += dx;
			}while(y0 <= y1);
		} else {
			do{
				if (err >= dx)
				{
					err -= dx;
					y0++;
				}
				plot(x0, y0, c);
				x0++;
				err += dy;
			}while(x0 <= x1);
		}
	} else {
		if (dy < -dx){
			do{
				if (err >= -dy)
				{
					err += dy;
					x0++;
				}
				plot(x0, y0, c);
				y0--;
				err += dx;
			}while(y0 >= y1);
		} else {
			do{
				if (err >= dx)
				{
					err -= dx;
					y0--;
				}
				plot(x0, y0, c);
				x0++;
				err -= dy;
			}while(x0 <= x1);
		}
	}

}

int main (void)
{
	Color wash_color;
		wash_color.r = 255;
		wash_color.g = 255;
		wash_color.b = 255;
	wash(wash_color);
	
	Color line_color;
		line_color.r = 0;
		line_color.g = 0;
		line_color.b = 0;
	
	line(50, 250, 450, 250, line_color); // axis
	line(250, 50, 250, 450, line_color);
	
	line(50, 50, 50, 450, line_color); // border
	line(50, 50, 450, 50, line_color);
	line(450, 50, 450, 450, line_color);
	line(450, 450, 50, 450, line_color);
	
	line_color.r = 255;
	
	line(250, 250, 450, 350, line_color); 
	line(250, 250, 450, 450, line_color);
	
	line(250, 250, 450, 150, line_color);
	line(250, 250, 450, 50, line_color);
	
	line(250, 250, 350, 450, line_color);
	line(250, 250, 350, 50, line_color);
	
	line(250, 250, 50, 350, line_color); 
	line(250, 250, 50, 450, line_color);
	
	line(250, 250, 50, 150, line_color);
	line(250, 250, 50, 50, line_color);
	
	line(250, 250, 150, 450, line_color);
	line(250, 250, 150, 50, line_color);
		
	display();
	return 0;
}	