/*
 * -----------------------------------------------------------------------------
 * Copyright (c) 2008-2009 Anders Martensson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * -----------------------------------------------------------------------------
 */

#include <time.h>
#include <pthread.h>
#include <ncurses.h>

int main() {
	initscr();
	cbreak();
	noecho();
	keypad(stdscr, TRUE);
	curs_set(0);

	srand((unsigned)time(0));
	int starter = (rand() % 2) + 1;
	int ball_y = LINES / 2;
	int ball_x;
	if(starter == 1)
		ball_x = 4;
	else
		ball_x = COLS - 5;
	int ball_d = (rand() % 4) + 1;			/* 1 nw, 2 ne, 3 se, 4 sw */

	int right_paddle_y = LINES / 2 - 3;
	int right_paddle_x = COLS - 3;
	int left_paddle_y = LINES / 2 - 3;
	int left_paddle_x = 2;

	int i;
	for(i = 1; i < LINES - 1; i++)
		mvprintw(i, COLS / 2, "|");
	for(i = 0; i < COLS; i++) {
		mvprintw(0, i, "-");
		mvprintw(LINES - 1, i, "-");
	}

	mvprintw(ball_y, ball_x, "O");
	for(i = 0; i < 7; i++)
		mvprintw(right_paddle_y + i, right_paddle_x, "#");
	for(i = 0; i < 7; i++)
		mvprintw(left_paddle_y + i, left_paddle_x, "#");

	char message1[] = "Press any key to start playing.";
	char message2[] = "Left player goes up with r/y and down with f/i.";
	char message3[] = "Right player goes up with u/c and down with j/t.";
	char message4[] = "Quit with q.";
	mvprintw(LINES / 2 - 2, COLS / 2 - (strlen(message1) / 2), "%s", message1);
	mvprintw(LINES / 2 - 1, COLS / 2 - (strlen(message2) / 2), "%s", message2);
	mvprintw(LINES / 2, COLS / 2 - (strlen(message3) / 2), "%s", message3);
	mvprintw(LINES / 2 + 1, COLS / 2 - (strlen(message4) / 2), "%s", message4);

	refresh();

	int ch;
	while(ch = getch()) {
		if(ch == 'q') {
			endwin();
			return 0;
		} else
			break;
	}

	clear();
	for(i = 0; i < 7; i++)
		mvprintw(right_paddle_y + i, right_paddle_x, "#");
	for(i = 0; i < 7; i++)
		mvprintw(left_paddle_y + i, left_paddle_x, "#");
	for(i = 0; i < COLS; i++) {
		mvprintw(0, i, "-");
		mvprintw(LINES - 1, i, "-");
	}
	refresh();

	int check_ball() {
		int status = 0;
		switch(ball_d) {
			case 1:
				if(ball_y - 1 == 0)
					ball_d = 4;
				else if(ball_x - 1 == 2) {
					if(ball_y - 1 < left_paddle_y - 1 || ball_y - 1 > left_paddle_y + 6)
						status = 2;
					else
						ball_d = 2;
				}
				break;
			case 2:
				if(ball_y - 1 == 0)
					ball_d = 3;
				else if(ball_x + 1 == COLS - 3) {
					if(ball_y - 1 < right_paddle_y || ball_y - 1 > right_paddle_y + 7)
						status = 1;
					else
						ball_d = 1;
				}
				break;
			case 3:
				if(ball_y + 1 == LINES - 1)
					ball_d = 2;
				else if(ball_x + 1 == COLS - 3) {
					if(ball_y + 1 < right_paddle_y || ball_y + 1 > right_paddle_y + 7)
						status = 1;
					else
						ball_d = 4;
				}
				break;
			case 4:
				if(ball_y + 1 == LINES - 1)
					ball_d = 1;
				else if(ball_x - 1 == 2) {
					if(ball_y + 1 < left_paddle_y - 1 || ball_y + 1 > left_paddle_y + 6)
						status = 2;
					else
						ball_d = 3;
				}
				break;
		}
		return status;
	}

	void *move_ball() {
		while(1) {
			mvprintw(ball_y, ball_x, " ");
			for(i = 1; i < LINES - 1; i++)
				mvprintw(i, COLS / 2, "|");
			switch(ball_d) {
				case 1:
					ball_y--;
					ball_x--;
					break;
				case 2:
					ball_y--;
					ball_x++;
					break;
				case 3:
					ball_y++;
					ball_x++;
					break;
				case 4:
					ball_y++;
					ball_x--;
					break;
			}
			mvprintw(ball_y, ball_x, "O");
			refresh();
			usleep(60000);
			int ball_status = check_ball();
			if(ball_status == 1) {
				mvprintw(ball_y, ball_x, " ");
				mvprintw(LINES / 2, COLS / 2 - 13, "The player on the left won!");
				refresh();
				break;
			} else if(ball_status == 2) {
				mvprintw(ball_y, ball_x, " ");
				mvprintw(LINES / 2, COLS / 2 - 14, "The player on the right won!");
				refresh();
				break;
			}		
		}
	}

	pthread_t ball_thread;
	pthread_create(&ball_thread, NULL, move_ball, NULL);

	while((ch = getch()) != 'q') {
		if(ch == 'r' || ch == 'y') {
			if(left_paddle_y > 1) {
				for(i = 0; i < 7; i++)
					mvprintw(left_paddle_y + i, left_paddle_x, " ");
				left_paddle_y--;
				for(i = 0; i < 7; i++)
					mvprintw(left_paddle_y + i, left_paddle_x, "#");
			}
		} else if(ch == 'f' || ch == 'i') {
			if(left_paddle_y + 6 < LINES - 2) {
				for(i = 0; i < 7; i++)
					mvprintw(left_paddle_y + i, left_paddle_x, " ");
				left_paddle_y++;
				for(i = 0; i < 7; i++)
					mvprintw(left_paddle_y + i, left_paddle_x, "#");
			}
		} else if(ch == 'u' || ch == 'c') {
			if(right_paddle_y > 1) {
				for(i = 0; i < 7; i++)
					mvprintw(right_paddle_y + i, right_paddle_x, " ");
				right_paddle_y--;
				for(i = 0; i < 7; i++)
					mvprintw(right_paddle_y + i, right_paddle_x, "#");
			}
		} else if(ch == 'j' || ch == 't') {
			if(right_paddle_y + 6 < LINES - 2) {
				for(i = 0; i < 7; i++)
					mvprintw(right_paddle_y + i, right_paddle_x, " ");
				right_paddle_y++;
				for(i = 0; i < 7; i++)
					mvprintw(right_paddle_y + i, right_paddle_x, "#");
			}
		}
		refresh();
	}

	endwin();

	return 0;
}

