#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

#include "graphics.h"
#include "grphcon.h"
#include "ui.h"
#include "id3.h"
#include "ff.h"
#include "key_ctrl.h"

#define LCD_H_SIZE 320
#define LCD_V_SIZE 240

unsigned short color_table[] =
{
	0x0000,	//BLACK,
	0xf800,	//RED,
	0x07e0,	//GREEN,
	0x001f,	//BLUE,
	0xffe0,	//YELLOW,
	0x07ff,	//CYAN,
	0xf81f,	//MAGENTA,
	0xffff,	//WHITE,
};

static void display_from_vram(int px, int py, int xl, int yl, void* p)
{
	int y;
	for(y = 0; y < yl; y++)
	{
		memcpy(
			(void*)((int)(0x3C100000 - LCD_H_SIZE * LCD_V_SIZE * 2 * 2) + ((py + y) * LCD_H_SIZE + px) * 2),
			(void*)((int)p                                              + ((py + y) * LCD_H_SIZE + px) * 2),
			(size_t)(xl * 2)
		);
	}
	return;
};

int ui_printf(const char *control, ...)
{
	char buf[LCD_H_SIZE / sc_col_width * LCD_V_SIZE / sc_row_height];
	va_list vargs;

	va_start(vargs, control);
	vsprintf(buf, control, vargs);
	va_end(vargs);

	GCON_putstr(buf);

	display_from_vram(0, 0, LCD_H_SIZE, LCD_V_SIZE, (void*)GRA1_VRAM_BASE);
	return (strlen(buf) / (LCD_H_SIZE / sc_col_width)) + (strlen(buf) % (LCD_H_SIZE / sc_col_width) ? 1 : 0);
}

int ui_printf_(const char *control, ...)
{
	char buf[LCD_H_SIZE / sc_col_width * LCD_V_SIZE / sc_row_height];
	va_list vargs;

	va_start(vargs, control);
	vsprintf(buf, control, vargs);
	va_end(vargs);

	GCON_putstr(buf);

	return (strlen(buf) / (LCD_H_SIZE / sc_col_width)) + (strlen(buf) % (LCD_H_SIZE / sc_col_width) ? 1 : 0);
}

void ui_printf_c(int y, const char *control, ...)
{
	char buf[LCD_H_SIZE / sc_col_width * LCD_V_SIZE / sc_row_height];
	va_list vargs;

	va_start(vargs, control);
	vsprintf(buf, control, vargs);
	va_end(vargs);

	if(strlen(buf) < LCD_H_SIZE / sc_col_width - 2)
	{
		GCON_locate((LCD_H_SIZE / sc_col_width - strlen(buf)) / 2, y);
		GCON_putstr(buf);
	}
	return;
}

void ui_printf_l(const char *control, ...)
{
	char buf[LCD_H_SIZE / sc_col_width * LCD_V_SIZE / sc_row_height];
	va_list vargs;

	va_start(vargs, control);
	vsprintf(buf, control, vargs);
	va_end(vargs);

	GCON_putstrL(buf, LCD_H_SIZE / sc_col_width - 2);

	return;
}

//領域クリア（白）
void ui_vram_clear(int t)
{
	unsigned short* p = (unsigned short*)GRA1_VRAM_BASE;
	int n = 0;
	while(n++ < LCD_H_SIZE * LCD_V_SIZE)
	{
		*p++ = color_table[WHITE];
	}

	if(t)
	{
		display_from_vram(0, 0, LCD_H_SIZE, LCD_V_SIZE, (void*)GRA1_VRAM_BASE);
	}
	GCON_locate(0, 0);
	return;
}

void init_ui_disp(void)
{
	ui_vram_clear(0);

	ui_printf_c(0, "ＣＱ出版 インターフェース 2012年");
	ui_printf_c(1, "SH-2A基板 ＭＰ３プレーヤ");
	ui_printf_c(3, "メモリカードをセットしてください");

	//最下行にタッチボタンを表示
	ui_disp_pause(0);
	ui_disp_repeat(0);
	ui_disp_shuffle(0);

	display_from_vram(0, 0, LCD_H_SIZE, LCD_V_SIZE, (void*)GRA1_VRAM_BASE);
	return;
}

void init_ui(void)
{
	LCDpanel_Initialize();

	GCON_SelectPlane((PIXEL *)GRA1_VRAM_BASE);
	GCON_Initialize();

	GCON_set_color(color_table[BLACK], color_table[WHITE]);

	//初期画面表示
	init_ui_disp();
	return;
}

void ui_disp_pause(int t)
{
	GCON_locate(LCD_H_SIZE / sc_col_width / sc_col_width * 1 - 4, LCD_V_SIZE / sc_row_height - 1);
	if(key_pause())
		GCON_set_color(color_table[BLACK], color_table[RED]);
	else
		GCON_set_color(color_table[BLACK], color_table[WHITE]);
	ui_printf_("  PAUSE  ");
	GCON_set_color(color_table[BLACK], color_table[WHITE]);
	if(t)
		display_from_vram(
			(LCD_H_SIZE / sc_col_width / sc_col_width * 1 - 4) * sc_col_width,
			(LCD_V_SIZE / sc_row_height - 1) * sc_row_height,
			9 * sc_col_width,
			sc_row_height,
			(void*)GRA1_VRAM_BASE);
	return;
}

void ui_disp_repeat(int t)
{
	GCON_locate(LCD_H_SIZE / sc_col_width / sc_col_width * 3 - 4, LCD_V_SIZE / sc_row_height - 1);
	if(key_repeat())
		GCON_set_color(color_table[BLACK], color_table[YELLOW]);
	else
		GCON_set_color(color_table[BLACK], color_table[WHITE]);
	ui_printf_(" REPEAT ");
	GCON_set_color(color_table[BLACK], color_table[WHITE]);
	if(t)
		display_from_vram(
			(LCD_H_SIZE / sc_col_width / sc_col_width * 3 - 4) * sc_col_width,
			(LCD_V_SIZE / sc_row_height - 1) * sc_row_height,
			8 * sc_col_width,
			sc_row_height,
			(void*)GRA1_VRAM_BASE);
	return;
}

void ui_disp_shuffle(int t)
{
	GCON_locate(LCD_H_SIZE / sc_col_width / sc_col_width * 5 - 4, LCD_V_SIZE / sc_row_height - 1);
	if(key_shuffle())
		GCON_set_color(color_table[BLACK], color_table[BLUE]);
	else
		GCON_set_color(color_table[BLACK], color_table[WHITE]);
	ui_printf_(" SHUFFLE ");
	GCON_set_color(color_table[BLACK], color_table[WHITE]);
	if(t)
		display_from_vram(
			(LCD_H_SIZE / sc_col_width / sc_col_width * 5 - 4) * sc_col_width,
			(LCD_V_SIZE / sc_row_height - 1) * sc_row_height,
			9 * sc_col_width,
			sc_row_height,
			(void*)GRA1_VRAM_BASE);
	return;
}

//指定されたファイルのデータと，同じフォルダにあるmp3ファイルを表示
void ui_file_list(char* filename)
{
	FRESULT res;
	char dirname[128];
	int line = 0;
	int l;

	ui_vram_clear(0);

	//曲名，アルバム名，演奏者名を表示
	line += ui_printf_("%s", id3tag_tt2());
	ui_printf_("\r\n");
	line += ui_printf_("%s", id3tag_tal());
	ui_printf_("\r\n");
	line += ui_printf_("%s", id3tag_tp1());
	ui_printf_("\r\n");
	line += ui_printf_("\r\n");

	//指定されたファイルのフォルダパスを求める
	strcpy(dirname, filename);
	for(l = strlen(dirname) - 1; l && dirname[l] != '\\'; l--)
	{
		dirname[l] = '\0';
	}
	dirname[l] = '\0';

	DIR Dir;
	char Lfname[_MAX_LFN];
	FILINFO Finfo = {.lfname = 0, .lfsize = 0};
	int count = 0, i = 0, n = 0, s = 0;

	//フォルダにあるmp3ファイルの数をカウント
	res = f_opendir(&Dir, dirname);
	if(res != 0)goto error_return;

	while(1)
	{
		res = f_readdir(&Dir, &Finfo);
		if(res != FR_OK) break;
		if(!Finfo.fname[0]) break;

		if(strstr(Finfo.fname, ".mp3")
		|| strstr(Finfo.fname, ".MP3"))
		{
			count++;
			if(strstr(filename, Finfo.fname))
				i = count;
		}
	}

	//mp3ファイルのファイル名（ロング形式）を表示
	res = f_opendir(&Dir, dirname);
	if(res != 0)goto error_return;

	Finfo.lfname = Lfname;
	Finfo.lfsize = sizeof(Lfname);

	if(count < LCD_V_SIZE / sc_row_height - 1 - line - 1)
	{
		while(1)
		{
			res = f_readdir(&Dir, &Finfo);
			if(res != FR_OK) break;
			if(!Finfo.fname[0]) break;

			if(strstr(Finfo.fname, ".mp3")
			|| strstr(Finfo.fname, ".MP3"))
			{
				if(n++ < (LCD_V_SIZE / sc_row_height - 1 - line - 1))
				{
					if(strstr(filename, Finfo.fname))
						GCON_set_color(color_table[BLACK], color_table[CYAN]);
					ui_printf_l("%s", Lfname);
					GCON_set_color(color_table[BLACK], color_table[WHITE]);
					ui_printf_("\r\n");
				}
			}
		}
	}
	else
	{
		while(1)
		{
			res = f_readdir(&Dir, &Finfo);
			if(res != FR_OK) break;
			if(!Finfo.fname[0]) break;

			if(strstr(Finfo.fname, ".mp3")
			|| strstr(Finfo.fname, ".MP3"))
			{
				if(s++ > i - (LCD_V_SIZE / sc_row_height - 1 - line - 1))
				{
					if(n++ < (LCD_V_SIZE / sc_row_height - 1 - line - 1))
					{
						if(strstr(filename, Finfo.fname))
							GCON_set_color(color_table[BLACK], color_table[CYAN]);
						ui_printf_l("%s", Lfname);
						GCON_set_color(color_table[BLACK], color_table[WHITE]);
						ui_printf_("\r\n");
					}
				}
			}
		}
	}

	//最下行にタッチボタンを表示
	ui_disp_pause(0);
	ui_disp_repeat(0);
	ui_disp_shuffle(0);
	display_from_vram(0, 0, LCD_H_SIZE, LCD_V_SIZE, (void*)GRA1_VRAM_BASE);

error_return:
	return;
}
