/* File: cmovie.c */

/* Purpose: play cmovie files -DarkGod-Improv- */

#include "angband.h"

/*
 * Play a given cmovie
 */
s16b do_play_cmovie(cptr cmov_file)
{
	FILE *fff;

	int y, line = 0, x;
	int delay;

	char *s;

	char buf[1024];
	char cbuf[90];
	char ch;

	char mode = 0;


	/* Cmovie files are moved to the user directory on the multiuser systems */

	/* Build the filename */
	path_build(buf, 1024, ANGBAND_DIR_CMOV, cmov_file);

	/* File type is "TEXT" */
	FILE_TYPE(FILE_TYPE_TEXT);

	/* Grab permission */
	/* safe_setuid_grab(); */

	/* Read the file */
	fff = my_fopen(buf, "r");

	/* Drop permission */
	/* safe_setuid_drop(); */

	/* Failure */
	if (!fff) return ( -1);

	/* Save screen */
	character_icky = TRUE;
	Term_save();
	Term_clear();

	/* Give some usefull info */
	prt("While viewing the movie you can press Escape to exit, t/Space to switch between", 0, 0);
	prt("fluid more and step by step mode and any other key to step a frame in step by", 1, 0);
	prt("step mode.", 2, 0);
	prt("You can press D to do an html screenshot of the current frame.", 3, 0);
	prt("You can also use + and - to speed up/down the playing speed.", 5, 0);
	prt("Press any key when ready.", 8, 0);

	inkey();

	Term_clear();

	line = -1;

	delay = 1;

	/* Init to white */
	for (x = 0; x < 80; x++)
	{
		cbuf[x] = 'w';
	}

	/* Parse */
	while (0 == my_fgets(fff, buf, 1024))
	{
		/* Do not wait */
		inkey_scan = TRUE;
		ch = inkey();

		/* Stop */
		if (ch == ESCAPE) break;

		/* Change mode */
		else if (ch == 't')
		{
			mode = FALSE;
		}
		else if (ch == ' ')
		{
			mode = TRUE;
		}

		/* Change speed */
		else if (ch == '+')
		{
			delay--;
			if (delay < 0) delay = 0;
		}
		else if (ch == '-')
		{
			delay++;
			if (delay > 5) delay = 5;
		}
		else if (ch == 'D')
		{
			do_cmd_html_dump();
		}

		line++;

		/* Skip comments and blank lines */
		if (!buf[0] || (buf[0] == '#')) continue;

		/* Verify correct "colon" format */
		if (buf[1] != ':') break;

		/* Clean screen */
		if (buf[0] == 'C')
		{
			Term_clear();

			/* Next */
			continue;
		}

		/* Displays a textbox */
		if (buf[0] == 'B')
		{
			int len = strlen(buf + 2);

			/* Clear the line */
			Term_erase(0, 0, 255);

			/* Display the message */
			c_put_str(TERM_VIOLET, "###", 0, 0);
			c_put_str(TERM_ORANGE, buf + 2, 0, 3);
			c_put_str(TERM_VIOLET, "###", 0, 3 + len);
			c_put_str(TERM_WHITE, "(more)", 0, 6 + len);

			/* Next */
			continue;
		}

		/* Wait a key */
		if (buf[0] == 'W')
		{
			inkey();

			/* Next */
			continue;
		}

		/* Sleep */
		if (buf[0] == 'S')
		{
			long msec;

			/* Scan for the values */
			if (1 != sscanf(buf + 2, "%ld:", &msec))
			{
				return ( -2);
			}

			if (!mode)
			{
				Term_xtra(TERM_XTRA_DELAY, msec);
			}
			else
			{
				bool stop = FALSE;

				while (TRUE)
				{
					ch = inkey();

					/* Stop */
					if (ch == ESCAPE)
					{
						stop = TRUE;
						break;
					}
					/* Change mode */
					else if (ch == 't')
					{
						mode = FALSE;
						break;
					}
					/* Change mode */
					else if (ch == ' ')
					{
						if (mode) continue;
						mode = TRUE;
						break;
					}
					/* Change speed */
					else if (ch == '+')
					{
						delay--;
						if (delay < 0) delay = 0;
					}
					else if (ch == '-')
					{
						delay++;
						if (delay > 5) delay = 5;
					}
					else if (ch == 'D')
					{
						do_cmd_html_dump();
					}
					else break;
				}
				if (stop) break;
			}

			/* Next */
			continue;
		}

		/* Get color for the NEXT L line */
		if (buf[0] == 'E')
		{
			/* Find the colon before the name */
			s = strchr(buf + 2, ':');

			/* Verify that colon */
			if (!s) return ( -2);

			/* Nuke the colon, advance to the name */
			*s++ = '\0';

			/* Paranoia -- require a name */
			if (!*s) return ( -2);

			/* Get the index */
			y = atoi(buf + 2);

			C_COPY(cbuf, s, 80, char);

			/* Next... */
			continue;
		}

		/* Print a line */
		if (buf[0] == 'L')
		{
			/* Find the colon before the name */
			s = strchr(buf + 2, ':');

			/* Verify that colon */
			if (!s) return ( -2);

			/* Nuke the colon, advance to the name */
			*s++ = '\0';

			/* Paranoia -- require a name */
			if (!*s) return ( -2);

			/* Get the index */
			y = atoi(buf + 2);

			for (x = 0; x < 80; x++)
			{
				Term_putch(x, y, color_char_to_attr(cbuf[x]), s[x]);

				/* Reinit to white */
				cbuf[x] = 'w';
			}
			Term_redraw_section(0, y, 79, y);

			/* Next... */
			continue;
		}

		/* Update 1 char */
		if (buf[0] == 'P')
		{
			int x, y, a, c;

			/* Scan for the values */
			if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
			                &x, &y, &c, &a))
			{
				a = 'w';
				if (3 != sscanf(buf + 2, "%d:%d:%d",
				                &x, &y, &c)) return ( -2);
			}

			Term_putch(x, y, color_char_to_attr(cbuf[x]), c);
			Term_redraw_section(x, y, x + 1, y + 1);

			/* Next... */
			continue;
		}
	}

	/* Load screen */
	Term_load();
	character_icky = FALSE;

	/* Close */
	my_fclose(fff);

	return (0);
}


/*
 * Start the recording of a cmovie
 */
void do_record_cmovie(cptr cmovie)
{
	char buf[1024];
	int fd = -1;
	int y;


	/* Build the filename */
	path_build(buf, 1024, ANGBAND_DIR_CMOV, cmovie);

	/* File type is "TEXT" */
	FILE_TYPE(FILE_TYPE_TEXT);

	/* Grab permission */
	/* safe_setuid_grab(); */

	/* Check for existing file */
	fd = fd_open(buf, O_RDONLY);

	/* Drop permission */
	/* safe_setuid_drop(); */

	/* Existing file */
	if (fd >= 0)
	{
		char out_val[160];

		/* Close the file */
		(void)fd_close(fd);

		/* Build query */
		(void)sprintf(out_val, "Replace existing file %s? ", cmovie);

		/* Ask */
		if (get_check(out_val)) fd = -1;
	}

	/* Be sure */
	if (!get_check("Ready to record(Press ctrl+D to enter a textual note while recording)?")) return;

	/* Grab privs */
	/* safe_setuid_grab(); */

	/* Open the non-existing file */
	if (fd < 0) movfile = my_fopen(buf, "w");

	/* And drop them */
	/* safe_setuid_drop(); */

	/* Invalid file */
	if (movfile == NULL)
	{
		msg_format("Cmovie recording failed!");

		return;
	}

	/* First thing: Record clear screen then enable the recording */
	fprintf(movfile, "# Generated by %s %ld.%ld.%ld\n",
	        game_module, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
	fprintf(movfile, "C:\n");
	last_paused = 0;
	do_movies = 1;
	cmovie_init_second();

	/* Mega Hack, get the screen */
	for (y = 0; y < Term->hgt; y++)
	{
		cmovie_record_line(y);
	}
}


/*
 * Stop the recording
 */
void do_stop_cmovie()
{
	if (do_movies == 1)
	{
		do_movies = 0;
		my_fclose(movfile);
	}
}


/*
 * Start a cmovie
 */
void do_start_cmovie()
{
	char name[90], rname[94];


	/* Should never happen */
	if (do_movies == 1) return;

	/* Default */
	sprintf(name, "%s", player_base);

	if (get_string("Cmovie name: ", name, 80))
	{
		if (name[0] && (name[0] != ' '))
		{
			sprintf(rname, "%s.cmv", name);

			if (get_check("Record(y), Play(n)?")) do_record_cmovie(rname);
			else do_play_cmovie(rname);
		}
	}
}


void cmovie_clean_line(int y, char *abuf, char *cbuf)
{
	const byte *ap = Term->scr->a[y];
	const char *cp = Term->scr->c[y];

	byte a;
	char c;

	int x;
	int wid, hgt;
	int screen_wid, screen_hgt;


	/* Retrieve current screen size */
	Term_get_size(&wid, &hgt);

	/* Calculate the size of dungeon map area */
	screen_wid = wid - (COL_MAP + 1);
	screen_hgt = hgt - (ROW_MAP + 1);

	/* For the time being, assume 80 column display XXX XXX XXX */
	for (x = 0; x < wid; x++)
	{
		/* Convert dungeon map into default attr/chars */
		if (!character_icky &&
		                ((x - COL_MAP) >= 0) &&
		                ((x - COL_MAP) < screen_wid) &&
		                ((y - ROW_MAP) >= 0) &&
		                ((y - ROW_MAP) < screen_hgt))
		{
			/* Retrieve default attr/char */
			map_info_default(y + panel_row_prt, x + panel_col_prt, &a, &c);

			abuf[x] = conv_color[a & 0xf];

			if (c == '\0') cbuf[x] = ' ';
			else cbuf[x] = c;
		}

		else
		{
			abuf[x] = conv_color[ap[x] & 0xf];
			cbuf[x] = cp[x];
		}
	}

	/* Null-terminate the prepared strings */
	abuf[x] = '\0';
	cbuf[x] = '\0';
}


/*
 * Write a record of a screen row into a cmovie file
 */
void cmovie_record_line(int y)
{
	char abuf[256];
	char cbuf[256];

	cmovie_clean_line(y, abuf, cbuf);

	/* Write a colour record */
	fprintf(movfile, "E:%d:%.80s\n", y, abuf);

	/* Write a char record */
	fprintf(movfile, "L:%d:%.80s\n", y, cbuf);
}


/*
 * Record a "text box"
 */
void do_cmovie_insert()
{
	char buf[81] = "";

	/* Dont record */
	do_movies = 2;

	while (get_string("Textbox(ESC to end): ", buf, 80))
	{
		fprintf(movfile, "B:%s\nW:\n", buf);
		buf[0] = '\0';
	}

	/* We reinit the time as to not count the time the user needed ot enter the text */
	cmovie_init_second();

	/* Continue recording */
	do_movies = 1;
}
