#include <stdio.h>
#include <gtk/gtk.h>
#include "../guiutils.h"
#include "../cdialog.h"
#include "../fb.h"
#include "../config.h"


#undef PROG_NAME_FULL
#define PROG_NAME_FULL		"Endeavour Mark II File Selector"


static void print_help(const gchar *prog_name);


#define ATOI(s)		(((s) != NULL) ? atoi(s) : 0)
#define ATOL(s)		(((s) != NULL) ? atol(s) : 0)
#define ATOF(s)		(((s) != NULL) ? atof(s) : 0.0f)
#define STRDUP(s)	(((s) != NULL) ? g_strdup(s) : NULL)

#define MAX(a,b)	(((a) > (b)) ? (a) : (b))
#define MIN(a,b)	(((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)	(MIN(MAX((a),(l)),(h)))
#define STRLEN(s)	(((s) != NULL) ? strlen(s) : 0)
#define STRISEMPTY(s)	(((s) != NULL) ? (*(s) == '\0') : TRUE)


/*
 *	Prints the help message.
 */
static void print_help(const gchar *prog_name)
{
	g_print(
"Usage: %s [startup_location] [options]\n",
	    prog_name
	);

	g_print("\n\
    Where [startup_location] specifies the full path to the startup\n\
    location.\n\
\n\
    Where [options] can be any of the following:\n\
\n\
        --title <s>             Specifies the title.\n\
        -t                      Same as --title.\n\
        --ok_button <s>         Specifies the label for the OK\n\
                                button.\n\
        --cancel_button <s>     Specifies the label for the Cancel\n\
                                button.\n\
	--file_type <ext> <name> Appends a file type to the list of\n\
                                available file types, the <ext>\n\
                                specifies a space-separated list of\n\
                                extensions and the <name> specifies\n\
                                a name or description of the file\n\
                                type.\n\
        -ft                     Same as --file_type.\n\
        --output_delim <c>      Specifiest he deliminator character\n\
                                to be used when separating multiple\n\
                                paths printed to stdout.\n\
        -od                     Same as --output_delim.\n\
        --limit_single          Only print the last selected object\n\
                                if multiple objects are selected.\n\
        -1                      Same as --limit_single.\n\
	--no_newline            Do not print a newline character at\n\
                                the end of the output.\n\
        -n                      Same as --no_newline.\n\
        --center <root|pointer> Specifies the window centering.\n\
        --geometry <WxH+X+Y>    Specifies the geometry.\n\
        --help                  Print help.\n\
        --version               Print version.\n\
\n\
    Returns values:\n\
\n\
        0       Cancel or error.\n\
        1       OK.\n\
\n"
	);
}

int main(int argc, char *argv[])
{
	gboolean	limit_single = FALSE,
			output_newline = TRUE;
	gchar output_deliminator = ',';
        const gchar	*title = "Select Object",
			*ok_btn_label = "OK",
			*cancel_btn_label = "Cancel";
	gboolean response;
	gint i, nfile_types = 0, npaths;
	const gchar *arg;
	gchar	*cwd = NULL,
		*startup_path = NULL,
		**paths_list;
        GtkWindowPosition center = GTK_WIN_POS_NONE;
        GdkRectangle *geometry = NULL;
        fb_type_struct **file_types_list = NULL, *file_type;

#define DO_FREE_LOCALS		{	\
 g_free(cwd);				\
 cwd = NULL;				\
 g_free(startup_path);			\
 startup_path = NULL;			\
 FileBrowserDeleteTypeList(		\
  file_types_list, nfile_types		\
 );					\
 file_types_list = NULL;		\
 nfile_types = 0;			\
 g_free(geometry);			\
 geometry = NULL;			\
}

        /* Parse arguments */
        for(i = 1; i < argc; i++)
        {
            arg = argv[i];
            if(arg == NULL)
                continue;

            /* Help */
            if(!g_strcasecmp(arg, "--help") ||
               !g_strcasecmp(arg, "-help") ||
               !g_strcasecmp(arg, "--h") ||
               !g_strcasecmp(arg, "-h")
            )
            {
                print_help(argv[0]);
		DO_FREE_LOCALS
                return(0);
            }
            /* Version */
            else if(!g_strcasecmp(arg, "--version") ||
                    !g_strcasecmp(arg, "-version")
            )
            {
                g_print(
		    "%s",
                    PROG_NAME_FULL " Version " PROG_VERSION "\n"
                    PROG_COPYRIGHT
                );
		DO_FREE_LOCALS
                return(0);
            }
            /* Title */
            else if(!g_strcasecmp(arg, "--title") ||
                    !g_strcasecmp(arg, "-title") ||
                    !g_strcasecmp(arg, "--t") ||
                    !g_strcasecmp(arg, "-t")
            )
            {
                i++;  
                arg = (i < argc) ? argv[i] : NULL;
                title = arg;
            }
            /* OK Button Label */
            else if(!g_strcasecmp(arg, "--ok_button") ||
                    !g_strcasecmp(arg, "-ok_button") ||
                    !g_strcasecmp(arg, "--ok-button") ||
                    !g_strcasecmp(arg, "-ok-button") ||
                    !g_strcasecmp(arg, "--ok_btn") ||
                    !g_strcasecmp(arg, "-ok_btn") ||
                    !g_strcasecmp(arg, "--ok-btn") ||
                    !g_strcasecmp(arg, "-ok-btn")
            )
            {
                i++;  
                arg = (i < argc) ? argv[i] : NULL;
                ok_btn_label = arg;
            }
            /* Cancel Button Label */
            else if(!g_strcasecmp(arg, "--cancel_button") ||
                    !g_strcasecmp(arg, "-cancel_button") ||
                    !g_strcasecmp(arg, "--cancel-button") ||
                    !g_strcasecmp(arg, "-cancel-button") ||
                    !g_strcasecmp(arg, "--cancel_btn") ||
                    !g_strcasecmp(arg, "-cancel_btn") ||
                    !g_strcasecmp(arg, "--cancel-btn") ||
                    !g_strcasecmp(arg, "-cancel-btn")
            )
            {
                i++;  
                arg = (i < argc) ? argv[i] : NULL;
                cancel_btn_label = arg;
            }
            /* File Type */
            else if(!g_strcasecmp(arg, "--file_type") ||
                    !g_strcasecmp(arg, "-file_type") ||
                    !g_strcasecmp(arg, "--ft") ||
                    !g_strcasecmp(arg, "-ft")
	    )
            {



	    }
	    /* Output deliminator */
	    else if(!g_strcasecmp(arg, "--output_deliminator") ||
                    !g_strcasecmp(arg, "-output_deliminator") ||
	            !g_strcasecmp(arg, "--output_delim") ||
                    !g_strcasecmp(arg, "-output_delim") ||
                    !g_strcasecmp(arg, "--od") ||
                    !g_strcasecmp(arg, "-od")
            )
	    {
		i++;
		arg = (i < argc) ? argv[i] : NULL;
		if(arg != NULL)
		{
		    output_deliminator = *arg;
		}
		else
		{
		    g_printerr(
"%s: Requires argument.\n",
			argv[i - 1]
		    );
		    DO_FREE_LOCALS
		    return(0);
		}
	    }
            /* Limit single */
            else if(!g_strcasecmp(arg, "--limit_single") ||
                    !g_strcasecmp(arg, "-limit_single") ||                 
                    !g_strcasecmp(arg, "--limit-single") ||
                    !g_strcasecmp(arg, "-limit_single") ||
                    !g_strcasecmp(arg, "--1") ||
                    !g_strcasecmp(arg, "-1")
            )
            {
		limit_single = TRUE;
            }
            /* Do not output newline */
            else if(!g_strcasecmp(arg, "--no_newline") ||
                    !g_strcasecmp(arg, "-no_newline") ||                 
                    !g_strcasecmp(arg, "--no-newline") ||
                    !g_strcasecmp(arg, "-no-newline") ||
                    !g_strcasecmp(arg, "--n") ||
                    !g_strcasecmp(arg, "-n")
            )
            {
                output_newline = FALSE;
            }
            /* Center */
            else if(!g_strcasecmp(arg, "--center") ||
                    !g_strcasecmp(arg, "-center")
            )
            {
                i++;
                arg = (i < argc) ? argv[i] : NULL;
                if(arg != NULL)
                {
                    if(!g_strcasecmp(arg, "root") ||
                       !g_strcasecmp(arg, "desktop") ||
                       !g_strcasecmp(arg, "center")
                    )
                        center = GTK_WIN_POS_CENTER;
                    else if(!g_strcasecmp(arg, "pointer") ||
                            !g_strcasecmp(arg, "mouse")
                    )
                        center = GTK_WIN_POS_MOUSE;
                    else if(!g_strcasecmp(arg, "none"))
                        center = GTK_WIN_POS_NONE;
                    else
		    {
                        g_printerr(
"%s: Available arguments are; root pointer none\n",
                            argv[i - 1]
                        );
			DO_FREE_LOCALS
			return(0);
		    }
                }
                else
                {
                    g_printerr(
"%s: Argument required.\n",
                        argv[i - 1]
                    );
                    DO_FREE_LOCALS
                    return(0);
                }
            }
            /* Geometry */
            else if(!g_strcasecmp(arg, "--geometry") ||
                    !g_strcasecmp(arg, "-geometry")
            )
            {
                i++;
                arg = (i < argc) ? argv[i] : NULL;
                if(arg != NULL)
                {
                    gint x, y, width, height;
                    g_free(geometry);
                    geometry = (GdkRectangle *)g_malloc0(
                        sizeof(GdkRectangle)
                    );
                    gdk_parse_geometry(
                        arg, &x, &y, &width, &height
                    );
                    geometry->x = x;
                    geometry->y = y;
                    geometry->width = width;
                    geometry->height = height;
                }
		else
                {
                    g_printerr(
"%s: Argument required.\n",
                        argv[i - 1]
                    );
                    DO_FREE_LOCALS
                    return(0);
                }
            }


	    /* All else assume startup location */
	    else if((*arg != '-') && (*arg != '+'))
	    {
		g_free(startup_path);
		startup_path = STRDUP(arg);
	    }
	}


        /* Initnialize GTK */
        gtk_set_locale();
	gtk_init(&argc, &argv);
	CDialogInit();
	FileBrowserInit();

	cwd = STRDUP(g_get_current_dir());

	/* If a startup location was specified then check if it
	 * is an absolute path
	 */
	if(startup_path != NULL)
	{
	    if(!g_path_is_absolute(startup_path))
	    {
		/* Not an absolute path, prefix the current working
		 * directory to it
		 */
		gchar *path = g_strdup_printf(
		    "%s%c%s",
		    cwd, G_DIR_SEPARATOR, startup_path
		);
		g_free(startup_path);
		startup_path = path;
	    }
	}
	else
	{
	    /* No startup location specified, use the current working
	     * directory instead
	     */
	    startup_path = STRDUP(cwd);
	}

	/* Create the file types list */
	FileBrowserTypeListNew(
	    &file_types_list, &nfile_types,
	    "*.*",
	    "All files"
	);

        /* Set dialog geometry */
        if(geometry != NULL)
        {
            GtkWidget *w = FileBrowserGetToplevel();
            if(w != NULL)
            {
                gtk_widget_set_uposition(w, geometry->x, geometry->y);
            }
        }
        else
        {
            /* No geometry set, so center the dialog */
            GtkWidget *w = FileBrowserGetToplevel();
            if((w != NULL) ? GTK_IS_WINDOW(w) : FALSE)
                gtk_window_set_position(GTK_WINDOW(w), center);
        }

	/* Map the file selector and wait for user response */
	paths_list = NULL;
	npaths = 0;
	file_type = NULL;
	response = FileBrowserGetResponse(
	    title,
	    ok_btn_label, cancel_btn_label,
	    startup_path,
	    file_types_list, nfile_types,
	    &paths_list, &npaths,
	    &file_type
	);
	if(response)
	{
	    const gchar *path;

	    if(limit_single)
	    {
		path = (npaths > 0) ? paths_list[npaths - 1] : NULL;
		if(path != NULL)
		    g_print("%s", path);
	    }
	    else
	    {
		for(i = 0; i < npaths; i++)
		{
		    path = paths_list[i];
		    if(path == NULL)
			continue;

		    if(i > 0)
			g_print("%c", output_deliminator);
		    g_print("%s", path);
		}
	    }

	    if(output_newline)
		g_print("\n");
	}

	FileBrowserShutdown();
	CDialogShutdown();

	DO_FREE_LOCALS

	return(response ? 1 : 0);
#undef DO_FREE_LOCALS
}
