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

#include "menu.h"
#include "sdlinterface.h"

#include <sys/stat.h>
#include <unistd.h>
#include<dirent.h>

#ifdef WIN32
#define bzero(A,B) memset(A,0,B)
#endif

#define MAX_FILELEN 29

typedef struct{
	char d_name[MAX_FILELEN+2];
	char d_type;
}fichero;

#ifdef DREAMCAST
#define chdir(A) fs_chdir(A)
#endif

extern char snes4all_image_file[];

#ifdef NORES256
char *text_str_load_separator="----------------------------------";
#else
char *text_str_load_separator=" -----------------------------";
#endif
char *text_str_load_dir="#DIR#";
char *text_str_load_title="        Filemanager       ";
fichero *text_dir_files=NULL;
int text_dir_num_files=0, text_dir_num_files_index=0;

char *text_load=NULL;

#define MAX_FILES_PER_DIR 1024
#define SHOW_MAX_FILES 13

#ifdef DREAMCAST
#define chdir(A) fs_chdir(A)
static char actual_dir[128];
#endif


static int min_in_dir=0, max_in_dir=SHOW_MAX_FILES;

static int compare_names(fichero *a, fichero *b)
{
	return strcmp(a->d_name,b->d_name);
}

static void copyCompleteName(char *dest, int n)
{
	char *src=text_dir_files[n].d_name;
	if (strlen(src)<MAX_FILELEN)
		strcpy(dest,src);
	else
	{
#ifdef DREAMCAST
		DIR *d=opendir(actual_dir);
#else
		DIR *d=opendir(".");
#endif
		if (d)
		{
			int i,indice=0,buscado=src[MAX_FILELEN+1];
			for(i=0;i<MAX_FILES_PER_DIR;i++)
			{
				struct dirent *actual=readdir(d);
				if (actual==NULL)
				{
					dest[0]=0;
					break;
				}
				if (!strncmp(src,actual->d_name,MAX_FILELEN))
				{
					if (indice==buscado)
					{
						strcpy(dest,actual->d_name);
						break;
					}
					indice++;
				}
			}
			closedir(d);
		}
		else
			dest[0]=0;
	}

}

static int checkFiles(void)
{
	char *buf=(char *)calloc(1,2046);
	int i,max=text_dir_num_files;
	int ret=(text_dir_num_files<1);
	if (max>16)
		max=16;
	for(i=0;(i<max)&&(!ret);i++)
	{
		copyCompleteName(buf,i);
		if (!buf[0])
			ret=1;
		else
		if (!text_dir_files[i].d_type)
		{
			FILE *f=fopen(buf,"rb");
			if (!f)
				ret=1;
			else
				fclose(f);
		}
		else
		if (strcmp(buf,".."))
		{
			DIR *d=opendir(buf);
			if (!d)
				ret=1;
			else
				closedir(d);
		}
	}
	free(buf);
	return ret;
}

static int getFiles(char *dir)
{
	int i,j;
	DIR *d;
	text_dir_num_files_index=0;
	text_dir_num_files=0;
	min_in_dir=0;
	max_in_dir=SHOW_MAX_FILES;

	if (text_dir_files!=NULL)
		free(text_dir_files);

	text_draw_window(96,64,140,32,"---");
	write_text(14,9,"Please wait");
	text_flip();

	text_dir_files=(fichero *)calloc(sizeof(fichero),MAX_FILES_PER_DIR);
#ifdef DREAMCAST
        if (!strcmp(dir,".."))
        {
                int ind;
                for(ind=strlen(actual_dir)-1;ind>0;ind--)
                        if (actual_dir[ind]=='/')
                        {
                                actual_dir[ind]=0;
                                break;
                        }
                d=opendir(actual_dir);
        }
        else
#endif
	d=opendir(dir);
	if (d==NULL)
		return -1;
	for(i=0;i<MAX_FILES_PER_DIR;i++)
	{
		struct dirent *actual=readdir(d);
		if (actual==NULL)
			break;
		if ((!strcmp(actual->d_name,"."))||(!strcmp(actual->d_name,"kick.rom"))||
		    (!strcmp(actual->d_name,"ip.bin"))||(!strcmp(actual->d_name,"1st_read.bin")))
		{
			i--;
			continue;
		}
		if (strlen(actual->d_name)>3)
		{
			char *final=(char *)&actual->d_name[strlen(actual->d_name)-3];
			if ((!strcmp(final,"ssn"))||(!strcmp(final,"SSN"))||(!strcmp(final,"srm"))||(!strcmp(final,"SRM"))||(!strcmp(final,"rtc"))||(!strcmp(final,"RTC")))
			{
				i--;
				continue;
			}
		}
		bzero(text_dir_files[i].d_name,MAX_FILELEN+1);
		strncpy(text_dir_files[i].d_name,actual->d_name,MAX_FILELEN);
		if (strlen(text_dir_files[i].d_name)==MAX_FILELEN)
		{
			int jjg,indice=0;
			for(jjg=0;jjg<i;jjg++)
				if (!(strcmp(text_dir_files[i].d_name,text_dir_files[jjg].d_name)))
						indice++;
			text_dir_files[jjg].d_name[MAX_FILELEN+1]=indice;
		}
#ifndef DREAMCAST
		{
			struct stat sstat;
			char *tmp=(char *)calloc(1,256);
			strcpy(tmp,dir);
			strcat(tmp,"/");
			strcat(tmp,text_dir_files[i].d_name);
			if (!stat(tmp, &sstat))
		        	if (S_ISDIR(sstat.st_mode))
					text_dir_files[i].d_type=4;
			free(tmp);
		}
#else
		text_dir_files[i].d_type=actual->d_type & 4;
#endif
	}
	closedir(d);
	text_dir_num_files=i;

#ifndef DREAMCAST
        chdir(dir);
#else
        if (strcmp(dir,MENU_DIR_DEFAULT))
        {
                if (strcmp(dir,".."))
                {
                        strcat(actual_dir,"/");
                        strcat(actual_dir,dir);
                }
        }
        chdir(actual_dir);
        if (strcmp(actual_dir,MENU_DIR_DEFAULT))
        {
		strcpy(text_dir_files[i].d_name,"..");
                text_dir_files[i].d_type=4;
                if (text_dir_num_files>0)
                {
                        char *pptmp=(char *)calloc(1,256);
                        int tmptype=text_dir_files[0].d_type;
                        strcpy(pptmp,text_dir_files[0].d_name);
                        text_dir_files[0].d_type=text_dir_files[text_dir_num_files].d_type;
                        text_dir_files[text_dir_num_files].d_type=tmptype;
                        strcpy(text_dir_files[0].d_name,text_dir_files[text_dir_num_files].d_name);
                        strcpy(text_dir_files[text_dir_num_files].d_name,pptmp);
                        free(pptmp);
                }
                text_dir_num_files++;
	}
#endif

	for(i=0;i<text_dir_num_files;i++)
	{
		if (text_dir_files[i].d_type==0)
			for(j=i;j<text_dir_num_files;j++)
				if (text_dir_files[j].d_type==4)
				{
					char *ctmp=(char *)calloc(1,256);
					strcpy(ctmp,text_dir_files[j].d_name);
					strcpy(text_dir_files[j].d_name,text_dir_files[i].d_name);
					strcpy(text_dir_files[i].d_name,ctmp);
					text_dir_files[i].d_type=4;
					text_dir_files[j].d_type=0;
					free(ctmp);
					break;
				}
	}
	for(i=0;i<text_dir_num_files;i++)
		if (text_dir_files[i].d_type==0)
		{
			qsort((void *)&text_dir_files[i],text_dir_num_files-i,sizeof(fichero),(int (*)(const void*, const void*))compare_names);
			break;
		}
	return 0;
}

#ifdef NORES256
#define R_X 80-64
#define R_W 110+64+64
#define R_XX 0
#define R_WW 0
#define R_T 0
#define R_T2 0
#else
#define R_X 80-32-8
#define R_W 110+64+32+8
#define R_XX 4*8
#define R_WW 0
#define R_T 2
#define R_T2 2
#endif

static void draw_loadMenu()
{
	int i,j;
	static int b=0;
	int bb=(b&3); //(b%6)/3;
	SDL_Rect r;
	extern SDL_Surface *text_screen;
	r.x=R_X-R_XX; r.y=0; r.w=R_W+R_WW; r.h=240;

	text_draw_background();
	text_draw_window(R_X,12,R_W+50,220,text_str_load_title);

	if (text_dir_num_files_index<min_in_dir)
	{
		min_in_dir=text_dir_num_files_index;
		max_in_dir=text_dir_num_files_index+SHOW_MAX_FILES;
	}
	else
		if (text_dir_num_files_index>=max_in_dir)
		{
			max_in_dir=text_dir_num_files_index+1;
			min_in_dir=max_in_dir-SHOW_MAX_FILES;
		}
	if (max_in_dir>text_dir_num_files)
		max_in_dir=text_dir_num_files-min_in_dir;


	for (i=min_in_dir,j=1;i<max_in_dir;i++,j+=2)
	{
		write_text(3+R_T,j,text_str_load_separator);

		SDL_SetClipRect(text_screen,&r);

		if ((text_dir_num_files_index==i)&&(bb))
			write_text_sel(4+R_T,j+1,(char *)&text_dir_files[i].d_name);
		else
			write_text(4+R_T,j+1,(char *)&text_dir_files[i].d_name);

		SDL_SetClipRect(text_screen,NULL);

		if (text_dir_files[i].d_type==4)
			write_text(32-R_T2,j+1,text_str_load_dir);
	}
	write_text(3+R_T,j,text_str_load_separator);
	text_flip();
	b++;
}

static int key_loadMenu()
{
	int end=0;
	int left=0, right=0, up=0, down=0, hit0=0, hit1=0;
	SDL_Event event;

	while (SDL_PollEvent(&event) > 0)
	{
		if (event.type == SDL_QUIT)
			end=-1;
		else
		if (event.type == SDL_KEYDOWN)
		{
			sound_play_beep();
			switch(event.key.keysym.sym)
			{
				case SDLK_RIGHT: right=1; break;
				case SDLK_LEFT: left=1; break;
				case SDLK_UP: up=1; break;
				case SDLK_DOWN: down=1; break;
				case SDLK_RETURN:
				case SDLK_LCTRL: hit0=1; break;
				case SDLK_LALT: hit1=1; break;
				case SDLK_TAB:
						if (text_dir_num_files)
							text_dir_num_files_index=text_dir_num_files-1;
						break;
				case SDLK_BACKSPACE:
						text_dir_num_files_index=0;
						break;

			}
			if (hit0)
			{
				if ((text_dir_files[text_dir_num_files_index].d_type==4)||(!strcmp((char *)&text_dir_files[text_dir_num_files_index].d_name,"."))||(!strcmp((char *)&text_dir_files[text_dir_num_files_index].d_name,"..")))
				{
					char *tmp=(char *)calloc(1,512);
					strcpy(tmp,text_dir_files[text_dir_num_files_index].d_name);
					if (getFiles(tmp))
						end=-1;
					free(tmp);
				}
				else
				{
					copyCompleteName(snes4all_image_file,text_dir_num_files_index);
					end=1;
				}
			}
			else if (hit1)
				end=-1;
			else if ((up)&&(text_dir_num_files_index>0))
				text_dir_num_files_index--;
			else if ((down)&&(text_dir_num_files_index+1!=text_dir_num_files))
				text_dir_num_files_index++;
			else if (left)
			{
				text_dir_num_files_index-=SHOW_MAX_FILES;
				if (text_dir_num_files_index<0)
					text_dir_num_files_index=0;
			}
			else if (right)
			{
				text_dir_num_files_index+=SHOW_MAX_FILES;
				if (text_dir_num_files_index+1>=text_dir_num_files)
					text_dir_num_files_index=text_dir_num_files-1;
			}
		}
	}

	return end;
}

static void raise_loadMenu()
{
	int i;

	text_draw_background();
	text_flip();
	for(i=0;i<10;i++)
	{
		text_draw_background();
		text_draw_window(80-64,(10-i)*24,160+64+64,220,text_str_load_title);
		text_flip();
	}
}

static void unraise_loadMenu()
{
	int i;

	for(i=9;i>=0;i--)
	{
		text_draw_background();
		text_draw_window(80-64,(10-i)*24,160+64+64,220,text_str_load_title);
		text_flip();
	}
	text_draw_background();
	text_flip();
}


int getDefaultFiles(void)
{
#ifdef DREAMCAST
	strcpy(actual_dir,MENU_DIR_DEFAULT);
#endif
	return(getFiles(MENU_DIR_DEFAULT));
}

int run_menuLoad()
{
	int end=0;

	if (text_dir_files==NULL)
		end=getDefaultFiles();
	else
		if (checkFiles())
			end=getDefaultFiles();

//	text_dir_num_files_index=0;

	raise_loadMenu();
	while(!end)
	{
		draw_loadMenu();
		end=key_loadMenu();
	}
	unraise_loadMenu();

	return end;
}
