/* $Id: gui_selectfile.c,v 1.4 2014/02/12 23:05:35 steffen Exp $ */
/***************************************************************************
 *            gui_selectdir.c
 *
 *  Copyright (C) 2013  Steffen Pohle
 *  steffen@gulpe.de
 ****************************************************************************/

/* 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * main.c is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU  General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "osmroute.h"
#include "draw.h"
#include "gui.h"
#include "system.h"

#include <sys/types.h>
#include <dirent.h>

void gui_sfile_close ();
void gui_sfile_update ();
void gui_sfile_clear ();
void gui_sfile_clicklist (int nr);

GUIWindow wsfile = {0};
GUIItem *wsf_close = NULL;
GUIItem *wsf_file = NULL;
GUIItem *wsf_flist = NULL;

char **wsf_list = NULL;
int wsf_listmax = 0;
char wsf_select_file[LEN_FILENAME];

char *gui_sfile_show (char *startpath) {
    if (wsfile.screen == NULL) gui_window_new (&wsfile, 220, 250, _("Select File"));
    wsfile.screen_changed = 1;
    wsfile.style = WGUI_S_VCENTER | WGUI_S_HCENTER;

    /* close Button */
    if (wsf_close == NULL) wsf_close = gui_button_new (_("Close"), 50, 220, 100, 20);
    GUI_BUTTON_T (wsf_close)->callback_clicked = (void*) gui_sfile_close;
 	gui_window_item_add (&wsfile, wsf_close);

    if (wsf_file == NULL) wsf_file = gui_entry_new (startpath, 10, 25, 200, 25);
 	gui_window_item_add (&wsfile, wsf_file);

	if (wsf_flist == NULL) wsf_flist = gui_list_new (10, 55, 200, 140);
	GUI_LIST_T (wsf_flist)->callback_selectitem = gui_sfile_clicklist;
	GUI_LIST_T (wsf_flist)->data = wsf_list;
	gui_window_item_add (&wsfile, wsf_flist);

	gui_sfile_update ();

	gui_show (&wsfile);
    while (currentwin == &wsfile) {
    	main_wnd_update ();
    }
    strncpy (wsf_select_file, GUI_ENTRY_T(wsf_file)->text, LEN_FILENAME-1);

    return wsf_select_file;
};


void gui_sfile_close () {
	gui_close ();
};


void gui_sfile_clicklist (int nr) {
	char fname[LEN_FILENAME];
	char *seperate;

	d_printf ("selected nr:%d   '%s'", nr, nr < wsf_listmax ? wsf_list[nr] : "nr >= wsf_listmax");
	if (nr >= wsf_listmax || wsf_list[nr] == NULL) return;

	if (strcmp (wsf_list[nr], ".") == 0) return;
	if (strcmp (wsf_list[nr], "..") == 0) {
		strncpy (fname, GUI_ENTRY_T(wsf_file)->text, LEN_FILENAME);
		while (strlen (fname)>1 && fname[strlen (fname) -1] == DIR_SEP)
			fname[strlen (fname)-1] = '\0';
		if (strlen (fname) > 1) {
			seperate = strrchr(fname, DIR_SEP);
			if (seperate != NULL) {
				seperate[0] = '\0';
			}
		}
		gui_entry_settext (wsf_file, fname);
	}
	else {
		if (GUI_ENTRY_T(wsf_file)->text[strlen (GUI_ENTRY_T(wsf_file)->text)-1] == DIR_SEP)
			snprintf (fname, LEN_FILENAME, "%s%s", GUI_ENTRY_T(wsf_file)->text, wsf_list[nr]);
		else
			snprintf (fname, LEN_FILENAME, "%s%c%s", GUI_ENTRY_T(wsf_file)->text, DIR_SEP, wsf_list[nr]);

		gui_entry_settext (wsf_file, fname);
	}

	gui_sfile_update ();
};


void gui_sfile_update () {
	int cnt;
	DIR *dir = NULL;
	struct dirent *direntry = NULL;
	char fname[LEN_FILENAME];
	struct stat stbuf;

	/* clear list and reopen directory */
	gui_sfile_clear ();
	if ((dir = opendir (GUI_ENTRY_T(wsf_file)->text)) == NULL) {
		/* if open fails, reopen with ROOT_DIR which is defined in system.h */
		gui_entry_settext (wsf_file, ROOT_DIR);
		if ((dir = opendir (GUI_ENTRY_T(wsf_file)->text)) == NULL) {
			d_printf ("could not open dir for reading. errno:%d '%s'", errno, strerror(errno));
			return;
		}
	}

	/* go through the directory but only add directory entries */
	cnt = wsf_listmax = 0;

	/* need more memory? */
	while ((direntry = readdir (dir))) {
		if (GUI_ENTRY_T(wsf_file)->text[strlen (GUI_ENTRY_T(wsf_file)->text)-1] == DIR_SEP)
			snprintf (fname, LEN_FILENAME, "%s%s", GUI_ENTRY_T(wsf_file)->text, direntry->d_name);
		else
			snprintf (fname, LEN_FILENAME, "%s%c%s", GUI_ENTRY_T(wsf_file)->text, DIR_SEP, direntry->d_name);
		if (stat(fname, &stbuf) == -1) {
			d_printf ("could not read stat of file: %s", fname);
			continue;
		}
		d_printf ("dir:%s", fname);
		if (cnt >= wsf_listmax) {
			/* save old pointer and counter */
			char **tmp = wsf_list;
			int i = wsf_listmax-1;

			/* allocate new list */
			wsf_listmax += 512;
			wsf_list = ml_malloc (wsf_listmax * sizeof(void*));
			memset (wsf_list, 0x0, wsf_listmax * sizeof(void*));

			/* copy list */
			if (tmp) {
				for (; i >= 0; i--) wsf_list[i] = tmp[i];
				ml_free (tmp);
			}
			/* setup new list */
			GUI_LIST_T (wsf_flist)->data = wsf_list;
		}

		wsf_list[cnt] = ml_malloc (LEN_FILENAME);
		
		if (S_ISDIR(stbuf.st_mode)) snprintf (wsf_list[cnt], LEN_FILENAME, "[%s]", direntry->d_name);
		else snprintf (wsf_list[cnt], LEN_FILENAME, "%s", direntry->d_name);

		d_printf ("added entry:%-3d '%s'", cnt, direntry->d_name);
		cnt++;
			
	}

	closedir (dir);
};


/*
 * remove all listentrys and free list
 */
void gui_sfile_clear () {
	int i;

	if (wsf_list == NULL) return;

	for (i = 0; wsf_list[i]; i++) {
		if (wsf_list[i]) ml_free (wsf_list[i]);
		wsf_list[i] = NULL;
	}
};

