/***************************************************************************

	textview.c

	Text viewer and Command list

***************************************************************************/

#include "psp.h"

#define issjis1(c)	(((c) >= 0x81 && (c) <= 0x9f) | ((c) >= 0xe0 && (c) <= 0xfc))
#define issjis2(c)	((c) >= 0x40 && (c) <= 0xfc && (c) != 0x7f)

typedef struct cmdlist_t
{
	int lines;
	char **line;
} CMDLIST;


static char *cmdbuf;
static char **cmdline;
static CMDLIST **cmd;
static int cmdflag;

static int top_page;
static int show_lines, show_pages;
static int num_lines, num_pages;
static int sel_page, prev_page;
static int sel_line, prev_line;
static int rows_line, rows_page;
static int page_min_sx;
static int page_max_sx;

static int check_text_encode(char *buf, int size)
{
	int i;
	int count1, count2, per;
	u8 *p = (u8 *)buf;

	count1 = 0;
	count2 = 0;

	for (i= 0; i < size;)
	{
		if (p[i] <= 0x20)
		{
			count2++;
			i++;
		}
		else if (p[i] == 0x97 && p[i + 1] == 0x97)
		{
			count2 += 2;
			i += 2;
		}
		else if (issjis1(p[i]) && issjis2(p[i + 1]))
		{
			count1++;
			i += 2;
		}
		else i++;
	}

	per = (count1 * 100) / (size - count2);

	if (per > 20)
		return CHARSET_SHIFTJIS;
	else
		return CHARSET_LATIN1;
}


void load_commandlist(const char *game_name)
{
	FILE *fp;
	char path[MAX_PATH];
	int i, j;
	int found, lines, nest;
	int fsize, start, end;
	int charset;
	char *p, linebuf[256];

	// initialize
	cmdbuf = NULL;
	cmdline = NULL;
	cmd = NULL;
	num_lines = 0;
	num_pages = 0;
	sel_page = 0;
	sel_line = 0;
	show_lines = 0;
	charset = CHARSET_DEFAULT;

	sprintf(path, "%sdata/command.dat", launchDir);

	if ((fp = fopen(path, "rb")) == NULL)
		return;

	while (fgets(linebuf, 255, fp) != NULL)
	{
		if (linebuf[0] == '$')
		{
			p = strtok(linebuf, "\r\n");
			if (strncmp(p, "$charset=", 9) == 0)
			{
				if (!stricmp(&p[9], "Shift_JIS"))
					charset = CHARSET_SHIFTJIS;
				else if (!stricmp(&p[9], "ISO-8859-1"))
					charset = CHARSET_LATIN1;
				else if (!stricmp(&p[9], "Latin1"))
					charset = CHARSET_LATIN1;
			}
			else if (!strncmp(p, "$info=", 6))
			{
				if (!strcmp(&p[6], game_name))
				{
					found = 1;
					break;
				}
			}
		}
	}

	if (!found)
	{
		fclose(fp);
		return;
	}

	start = ftell(fp);
	nest = 0;
	lines = 0;

	while (fgets(linebuf, 255, fp) != NULL)
	{
		if (linebuf[0] == '$')
		{
			p = strtok(linebuf, "\r\n");

			if (strncmp(p, "$cmd", 4) == 0)
			{
				num_pages++;
				nest++;
			}
			else if (strncmp(p, "$end", 4) == 0)
			{
				nest--;
				end = ftell(fp);
				num_lines = lines + 1;
			}
			else if (strncmp(p, "$info", 5) == 0)
			{
				break;
			}
		}
		lines++;
	}

	fsize = end - start;

	if ((cmdbuf = malloc(fsize + 16)) == NULL)
		goto error;

	memset(cmdbuf, 0, fsize + 16);

	fseek(fp, start, SEEK_SET);
	fread(cmdbuf, 1, fsize, fp);
	fclose(fp);
	fp = NULL;

	if (charset == CHARSET_DEFAULT)
		cmdflag = check_text_encode(cmdbuf, fsize);
	else
		cmdflag = charset;

	if ((cmdline = malloc(sizeof(char *) * num_lines)) == NULL)
		goto error;

	memset(cmdline, 0, sizeof(char *) * num_lines);

	cmdline[0] = strtok(cmdbuf, "\n");
	for (i = 1; i < num_lines; i++)
	{
		cmdline[i] = strtok(NULL, "\n");
		if (cmdline[i] == NULL) break;
	}

	for (i = 0; i < num_lines; i++)
	{
		if (strtok(cmdline[i], "\r\n") == NULL)
			cmdline[i][0] = 0;
	}

	if ((cmd = (CMDLIST **)malloc(sizeof(CMDLIST *) * num_pages)) == NULL)
		goto error;

	for (i = 0; i < num_pages; i++)
	{
		if ((cmd[i] = (CMDLIST *)malloc(sizeof(CMDLIST))) == NULL)
			goto error;

		cmd[i]->lines = 0;
		cmd[i]->line = NULL;
	}

	i = 0;
	nest = 0;
	lines = 0;
	while (lines < num_lines && i < num_pages)
	{
		strcpy(linebuf, cmdline[lines++]);

		if (linebuf[0] == '$')
		{
			if (strcmp(linebuf, "$cmd") == 0)
			{
				nest = 1;
			}
			else if (strcmp(linebuf, "$end") == 0)
			{
				nest = 0;
				i++;
			}
		}
		else if (nest)
		{
			cmd[i]->lines++;
		}
	}

	i = 0;
	j = 0;
	nest = 0;
	lines = 0;
	while (lines < num_lines && i < num_pages)
	{
		strcpy(linebuf, cmdline[lines++]);

		if (linebuf[0] == '$')
		{
			if (strcmp(linebuf, "$cmd") == 0)
			{
				nest = 1;

				if ((cmd[i]->line = malloc(sizeof(char *) * cmd[i]->lines)) == NULL)
					goto error;

				j = 0;
			}
			else if (strcmp(linebuf, "$end") == 0)
			{
				nest = 0;
				i++;
			}
		}
		else if (nest)
		{
			cmd[i]->line[j++] = cmdline[lines - 1];
		}
	}

	top_page = 0;
	sel_page = prev_page = 0;
	sel_line = prev_line = 0;

	page_min_sx = 12 + 46 * 7;
	page_max_sx = 480;
	for (i = 0; i < num_pages; i++)
	{
		int x = 480 - (strlen(cmd[i]->line[0]) * 7 + 16);

		if (page_max_sx > x) page_max_sx = x;

		for (j = 0; j < cmd[i]->lines; j++)
		{
			x = 12 + strlen(cmd[i]->line[j]) * 7;

			if (page_min_sx < x) page_min_sx = x;
		}
	}

	if (cmdflag & CHARSET_SHIFTJIS)
		rows_line = 16;
	else
		rows_line = 14;

	show_lines = rows_line;
	num_lines = cmd[0]->lines;
	if (num_lines < show_lines)
		show_lines = num_lines;

	rows_page = 13;
	show_pages = rows_page;
	if (num_pages < show_pages)
		show_pages = num_pages;

	return;

error:
	free_commandlist();
	if (fp) fclose(fp);
}


void free_commandlist(void)
{
	int i, j;

	if (cmd)
	{
		for (i = 0; i < num_pages; i++)
		{
			if (cmd[i])
			{
				if (cmd[i]->line) free(cmd[i]->line);
				free(cmd[i]);
			}
		}
		free(cmd);
		cmd = NULL;
	}

	if (cmdline)
	{
		free(cmdline);
		cmdline = NULL;
	}

	if (cmdbuf)
	{
		free(cmdbuf);
		cmdbuf = NULL;
	}
}


void commandlist(int flag)
{
	int x, y, alpha;
	int update = 1, page_show_counter = 0;
	int mp3_paused = 0;
	char title[80], temp[32];
	extern const char *game_name;

	if (cmdbuf == NULL)
	{
#if JAPANESE_UI
		ui_popup("このゲーム用のコマンドリストがありません。");
#else
		ui_popup("Command list for this game not found.");
#endif
		return;
	}

	if (flag)
	{
		if (mp3_get_status() == MP3_PLAY)
		{
			mp3_pause(1);
			mp3_paused = 1;
		}
		sound_enable(0);

		scePowerSetClockFrequency(222, 222, 111);

		video_clear_screen();
		video_exit();
		video_init32();
	}

	pad_wait_clear();
	load_background(WP_CMDLIST);
	ui_popup_reset();

#if JAPANESE_UI
	sprintf(title, "コマンドリスト - %s", game_name);
#else
	sprintf(title, "Command list - %s", game_name);
#endif

	do
	{
		if (update)
		{
			update = 0;

			show_background();

			small_icon_shadow(8, 3, UI_COLOR(UI_PAL_TITLE), ICON_CMDLIST);
			uifont_print_shadow(36, 5, UI_COLOR(UI_PAL_TITLE), title);
			draw_battery_status(1);

			if (sel_line != 0)
				uifont_print_shadow(161, 24, UI_COLOR(UI_PAL_SELECT), FONT_UPTRIANGLE);

			if (cmdflag & CHARSET_SHIFTJIS)
			{
				for (y = 0; y < show_lines; y++)
					textfont_print(6, 37 + 14 * y, UI_COLOR(UI_PAL_SELECT), cmd[sel_page]->line[y + sel_line], cmdflag);
			}
			else
			{
				for (y = 0; y < show_lines; y++)
					textfont_print(6, 37 + 16 * y, UI_COLOR(UI_PAL_SELECT), cmd[sel_page]->line[y + sel_line], cmdflag);
			}

			if (sel_line + show_lines < num_lines)
				uifont_print_shadow(161, 260, UI_COLOR(UI_PAL_SELECT), FONT_DOWNTRIANGLE);

			if (page_show_counter >= 4)
			{
				alpha = 14;
				x = page_max_sx;
			}
			else if (page_show_counter > 0)
			{
				alpha = 14 - ((4 - page_show_counter) << 1);
				x = page_max_sx + ((page_min_sx - page_max_sx) >> 2) * (4 - page_show_counter);
			}
			else
			{
				alpha = 6;
				x = page_min_sx;
			}

			boxfill_alpha(x, 26, 479, 271, UI_COLOR(UI_PAL_BG1), alpha);

			for (y = 0; y < rows_page; y++)
			{
				if (top_page + y >= num_pages) break;

				if (top_page + y == sel_page)
				{
					uifont_print(x, 37 + 16 * y, UI_COLOR(UI_PAL_SELECT), FONT_RIGHTTRIANGLE);
					textfont_print(x + 14, 37 + 16 * y, UI_COLOR(UI_PAL_SELECT), cmd[top_page + y]->line[0], cmdflag);
				}
				else
					textfont_print(x + 14, 37 + 16 * y, UI_COLOR(UI_PAL_NORMAL), cmd[top_page + y]->line[0], cmdflag);
			}

#if JAPANESE_UI
			sprintf(temp, "%d/%d 項目", sel_page + 1, num_pages);
#else
			sprintf(temp, "%d/%d items", sel_page + 1, num_pages);
#endif
			x = uifont_get_string_width(temp);
			uifont_print(475 - x, 250, UI_COLOR(UI_PAL_SELECT), temp);

			update |= ui_show_popup(1);
			video_flip_screen(1);
		}
		else
		{
			update = ui_show_popup(0);
			video_wait_vsync();
		}

		if (page_show_counter)
		{
			update = 1;
			page_show_counter--;
		}

		pad_update();

		if (pad_pressed(PSP_CTRL_UP))
		{
			if (sel_line > 0) sel_line--;
		}
		else if (pad_pressed(PSP_CTRL_DOWN))
		{
			if (sel_line + show_lines < num_lines) sel_line++;
		}
		else if (pad_pressed(PSP_CTRL_LEFT))
		{
			if (sel_line > 0)
			{
				sel_line -= rows_line;
				if (sel_line < 0) sel_line = 0;
			}
		}
		else if (pad_pressed(PSP_CTRL_RIGHT))
		{
			if (sel_line + show_lines < num_lines)
			{
				sel_line += rows_line;
				if (sel_line + show_lines > num_lines)
					sel_line = num_lines - show_lines;
			}
		}
		else if (pad_pressed(PSP_CTRL_LTRIGGER))
		{
			if (sel_page > 0)
			{
				sel_page--;
				top_page = 0;
				show_lines = rows_line;
				num_lines = cmd[sel_page]->lines;
				if (num_lines < show_lines)
					show_lines = num_lines;
				sel_line = 0;
			}
			page_show_counter = 12 + 4;
		}
		else if (pad_pressed(PSP_CTRL_RTRIGGER))
		{
			if (sel_page < num_pages - 1)
			{
				sel_page++;
				top_page = 0;
				show_lines = rows_line;
				num_lines = cmd[sel_page]->lines;
				if (num_lines < show_lines)
					show_lines = num_lines;
				sel_line = 0;
			}
			page_show_counter = 12 + 4;
		}
		else if (pad_pressed(PSP_CTRL_START))
		{
			ui_save_screenshot("menu6");
			pad_wait_clear();
		}
		else if (pad_pressed(PSP_CTRL_TRIANGLE))
		{
			help(HELP_COMMANDLIST);
			update = 1;
		}

		if (top_page > num_pages - rows_page) top_page = num_pages - rows_page;
		if (top_page < 0) top_page = 0;
		if (sel_page >= top_page + rows_page) top_page = sel_page - rows_page + 1;
		if (sel_page < top_page) top_page = sel_page;

		if ((sel_line != prev_line) || (sel_page != prev_page))
			update = 1;

		prev_page = sel_page;
		prev_line = sel_line;

	} while (!pad_pressed(PSP_CTRL_CROSS));

	pad_wait_clear();
	ui_popup_reset();

	if (flag)
	{
		video_clear_screen32();
		video_exit32();

		video_init();
		video_clear_screen();

		set_cpu_clock();

		init_autoframeskip();
		blit_clear_all_cache();

		sound_set_volume();
		sound_enable(1);

		mp3_file_reopen();
		mp3_set_volume();
		if (mp3_paused) mp3_pause(0);
	}
	else
	{
		load_background(WP_LOGO);
	}
}
