#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <termios.h>

void clrline(int width) {
	int i;
	
	putchar('\r');
	for (i = 0; i < width; i ++) {
		putchar(' ');
	}
	putchar('\r');
}

int get_line(char* line, FILE* fptr, int width, int* progress) {	
	int i;
	char ch;

	for (i = 0; i < width; i ++) {
		ch = fgetc(fptr);
		if (ch == -1) {
			line[i] = '\0';
			return -1;
		}
		line[i] = ch;
		(*progress) ++;
		if (ch == '\n') {
			line[i] = '\0';
			return 0;
		}
	}
	return 0;	
}

void print_footer(int progress, int file_size) {
	int position;

	position = (int)((double)progress / (double)file_size * 100); 
	printf("\x1b[36m" "--more-- (%d%%)" "\x1b[0m", position);
}

void disable_canonical_and_echo(struct termios info) {
	/* thx random guy from stackoverflow */
	tcgetattr(0, &info);          /* get current terminal attirbutes; 0 is the file descriptor for stdin */
	info.c_lflag &= ~ICANON;      /* disable canonical mode */

	info.c_lflag &= ~ECHO;      /* another thing i stole from another stackowerflow conversation */

	info.c_cc[VMIN] = 1;          /* wait until at least one keystroke available */
	info.c_cc[VTIME] = 0;         /* no timeout */
	tcsetattr(0, TCSANOW, &info); /* set immediately */
}

void enable_canonical_and_echo(struct termios info) {
	/* thx again */
	tcgetattr(0, &info);
	info.c_lflag |= ICANON;
	info.c_lflag |= ECHO;
	tcsetattr(0, TCSANOW, &info);
}

main (int argc, char* argv[]) {
	FILE* fptr;
	struct winsize w;
	int size_row;
	int size_col;
	int i;
	int ret;
	char ch;
	struct termios info;
	int progress = 0;
	int file_size;


	ioctl(0, TIOCGWINSZ, &w);
	size_row = w.ws_row;
	size_col = w.ws_col;

	char* line = (char*)malloc(size_col * sizeof(char));
	if (line == NULL) {
		printf("Memory allocation failed!\n");
		return 1;
	}

	if (argc == 1) {
		printf("Bad usage.\n\n");
		printf("Correct usage:\n");
		printf("\"more <file>\"\n");

		/* TODO:
		 * add pgdown for faster scrolling
		 * add end/down arrow for jump to end
		 * add support for multiple files (eventually)
		 * add support for input from stdin (quite important)
		 */

		return 1;
	}

	fptr = fopen(argv[1], "r");
	if (fptr == NULL) {
		printf("Can't open file %s", argv[1]);
		return 1;
	}
	
	fseek(fptr, 0L, SEEK_END);
	file_size = ftell(fptr);
	rewind(fptr);

	for (i = 0; i < size_row - 1; i++) {
		ret = get_line(line, fptr, size_col, &progress);
		printf("%s\n", line);
		if (ret == -1) {
			return 0;
		}
	}

	print_footer(progress, file_size);

	disable_canonical_and_echo(info);
	
	while (ret != -1) {
		ch = getchar();
		
		switch (ch) {
			case '\n':
				ret = get_line(line, fptr, size_col, &progress);
				clrline(size_col);
				printf("%s\n", line);
				print_footer(progress, file_size);
				break;
	
			case 'q':
				ret = -1;
				break;
		}
		if (progress == file_size) {
			clrline(size_col);
			enable_canonical_and_echo(info);
			return 0;
		}
	}

	enable_canonical_and_echo(info);
	clrline(size_col);

	fclose(fptr);
	return 0;
}
