/* $Id: e2_complete__files.c 638 2007-09-05 03:09:44Z tpgww $

Copyright (C) 2004-2007 tooar <tooar@gmx.net>

This file is part of emelFM2.
emelFM2 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, or (at your option)
any later version.

emelFM2 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 emelFM2; see the file GPL. If not, contact the Free Software
Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "e2_complete.h"
#include <unistd.h>
#include <glob.h>

/**
@brief create list of files (and non-files) that are valid completions of @a word
Only native completions are suported.
The string to be completed extends from after the ' ' (if any) preceding
the cursor position @a pos, to that position. But if @a pos = 0, the string
will be empty
If the string in question is from a dirline, the corresponding directory
is scanned for completions
For a dirline, @a line = @a word
This function temporarily changes the filesystem CWD

@param line utf8 string containing the whole line to be completed
@param word utf8 string, copy of part of @a line with the 'word' to be completed
@param pos 0-based index of cursor position (characters, not bytes) in @a line
@param found pointer to list to record matching items
@param flags pointer to bit-flags indicating type of match (dirs or files)
@param data discretionary data pointer
@param pane enumerator of pane to be used for getting dir string 1,2,0=current

@return the number of successful matches
*/
gint e2_complete_files (gchar *line, gchar *word, gint pos, GList **found,
	E2_CompleteFlags *flags, gpointer data, guint pane)
{
	printd (DEBUG, "complete_files (line:%s,word:%s,pos:%d,found:_,flags:%d,data:_)",
		line, word, pos, *flags);
	gchar *path, *pattern, *pattern_local;
#ifdef E2_VFS
	PlaceInfo *spacedata;
	switch (pane)
	{
		case E2PANE1:
			spacedata = app.pane1_view.spacedata;
			break;
		case E2PANE2:
			spacedata = app.pane2_view.spacedata;
			break;
		default:
			spacedata = curr_view->spacedata;
			break;
	}
	if (spacedata != NULL)
		return 0;	//no completion ATM for non-local places
#ifdef E2_VFSTMP
	make this work ?
#endif
#endif
	if (!g_path_is_absolute (word)
#ifdef E2_VFSTMP
		&& spacedata == NULL //cd only for native filesystem
#endif
		)
	{
		switch (pane)
		{
			case E2PANE1:
				path = app.pane1_view.dir;
				break;
			case E2PANE2:
				path = app.pane2_view.dir;
				break;
			default:
				path = curr_view->dir;
				break;
		}
		if (!e2_fs_chdir (path E2_ERR_NONE()))
			return 0;
	}

#ifdef VFS_TMP
	//FIXME use dir foreach func with callback to g_pattern_match*
#endif
	gint count;
	pattern = g_strconcat (word, "*", NULL);
	pattern_local = F_FILENAME_TO_LOCALE (pattern);
	glob_t matches;
	if (glob (pattern_local, GLOB_MARK, NULL, &matches) == 0)	//this doesn not support vfs matching
	{
		guint i;
		gboolean dirs = (*flags & E2_COMPLETE_FLAG_DIRS) && (!(*flags & E2_COMPLETE_FLAG_FILES));
		gboolean files = (*flags & E2_COMPLETE_FLAG_FILES) && (!(*flags & E2_COMPLETE_FLAG_DIRS));
		for (i = 0; i < matches.gl_pathc; i++)
		{
			if (dirs)
			{
				if (g_str_has_suffix (matches.gl_pathv[i], G_DIR_SEPARATOR_S))
					*found = g_list_append (*found, D_FILENAME_FROM_LOCALE (matches.gl_pathv[i]));
			}
			else
				if (files)
			{
				if (!g_str_has_suffix (matches.gl_pathv[i], G_DIR_SEPARATOR_S))
					*found = g_list_append (*found, D_FILENAME_FROM_LOCALE (matches.gl_pathv[i]));
			}
			else
				*found = g_list_append (*found, D_FILENAME_FROM_LOCALE (matches.gl_pathv[i]));
		}
		count = matches.gl_pathc;
		globfree (&matches);
	}
	else
		count = 0;

	//only relevant for native filesystem
//#ifdef E2_VFS
//	if (spacedata == NULL)
//#endif
		e2_fs_chdir (curr_view->dir E2_ERR_NONE());
	g_free (pattern);
	F_FREE (pattern_local);

	return count;
}
