/* spinner
 * by Chip Black
 *
 * spinner is public domain, do with it what you will.
 * Yes. It's that awesome.
 *
 * FUN THINGS TO DO WITH SPINNER
 * - Change the w and h variables below. My system can't really keep up
 *   with anything more than 40x20. I'm betting yours can do more.
 * - Change the DELAY to more or less. The rotation is synced to the
 *   clock, so all this does is change the frame rate. The 1000us delay
 *   below isn't really a 1000us delay, since the resolution of your
 *   system timer is probably far greater. Comment out the usleep call
 *   if you want spinner to look really smooth (and take up all of your
 *   CPU time).
 * - change the RATE constant. Note that if you want to increase the
 *   speed, you should probably also decrease the delay, or your
 *   animation will get choppy.
 * - Mess with the direction of the comparisons (or remove some of
 *   them). See what other rotating patterns you can make.
 */

#include <stdio.h>
#include <math.h>
#include <ncurses.h>
#include <unistd.h>
#include <sys/time.h>

#define DELAY 1000
// 360 degrees per second (in us)
#define RATE 360.0 / 1000000.0

int color = 0;

void spinner() {
	int w,h,i,j;
	int cw,ch;
	int r = 0;
	struct timeval tv;

	getmaxyx(stdscr, h, w);
	cw = w / 2;
	ch = h / 2;
	init_pair(1,COLOR_RED, COLOR_RED);
	init_pair(2,COLOR_BLACK, COLOR_BLACK);
	char pc,bc;
	pc = '*';
	if (color)
		bc = '-';
	else
		bc = ' ';

	while (1) {
		float a,b;
		gettimeofday(&tv,NULL);
		r = (int) ((float)tv.tv_usec * RATE);
		if (r == 360) r = 0;
		a = tan((r / 180.0) * 3.14159);
		b = tan(((r+90) / 180.0) * 3.14159);
		move(0,0);
		for (j = 0; j < h; j++) {
			for (i = 0; i < w; i++) {
				// y = mx + b
				if ((r > 90 && r <= 180) || (r > 270 && r < 360) || r == 0) {
					if ((j-ch) * 2 > a * (i-cw) && (j-ch) * 2 < b * (i-cw) ||
					    (j-ch) * 2 < a * (i-cw) && (j-ch) * 2 > b * (i-cw) ) {
						attrset(COLOR_PAIR(1));
						addch(pc);
					} else {
						attrset(COLOR_PAIR(2));
						addch(bc);
					}
				} else {
					if ((j-ch) * 2 > a * (i-cw) && (j-ch) * 2 > b * (i-cw) ||
					    (j-ch) * 2 < a * (i-cw) && (j-ch) * 2 < b * (i-cw) ) {
						attrset(COLOR_PAIR(1));
						addch(pc);
					} else {
						attrset(COLOR_PAIR(2));
						addch(bc);
					}
				}
			}
		}
		refresh();
		usleep(DELAY);
	}
}

int main(int argc, char *argv[]) {
	if (argc == 2 && argv[1][0] == 'c') {
		color = 1;
	}
	initscr();
	if (color)
		start_color();
	cbreak(); noecho(); nonl();
	spinner();

	return 0;
}

