#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <unistd.h>

#include "../../include/disk.h"
#include "../../include/prochandle.h"

#include "../edv_interps.h"
#include "edv_utils.h"
#include "edv_context.h"
#include "edv_window.h"
#include "config.h"


static gchar *EDVWindowCopyCompletePath(const gchar *path);
static void EDVWindowExec(edv_context_struct *ctx, const gchar *cmd);

void EDVWindowBrowserNew(
	edv_context_struct *ctx, const gchar *path
);
void EDVWindowImageBrowserNew(
	edv_context_struct *ctx, const gchar *path
);
void EDVWindowArchiverNew(
	edv_context_struct *ctx, const gchar *path
);
void EDVWindowRecycleBinMap(edv_context_struct *ctx);

void EDVWindowPropertiesDialogNewWithPage(
	edv_context_struct *ctx, const gchar *path,
	const gchar *page_name
);
void EDVWindowPropertiesDialogNew(
	edv_context_struct *ctx, const gchar *path
);

void EDVWindowOptionsWindowMapWithPage(
	edv_context_struct *ctx, const gchar *page_name
);
void EDVWindowOptionsWindowMap(edv_context_struct *ctx);

void EDVWindowCustomizeWindowMapWithPage(
	edv_context_struct *ctx, const gchar *page_name
);
void EDVWindowCustomizeWindowMap(edv_context_struct *ctx);

void EDVWindowDevicesWindowMap(edv_context_struct *ctx);
void EDVWindowMIMETypesWindowMap(edv_context_struct *ctx);

void EDVWindowRunDialogMapWithCommand(
	edv_context_struct *ctx, const gchar *command
);
void EDVWindowRunDialogMap(edv_context_struct *ctx);

void EDVWindowFindWindowMapWithLocation(
	edv_context_struct *ctx, const gchar *location
);
void EDVWindowFindWindowMap(edv_context_struct *ctx);

void EDVWindowAboutDialogMapWithPage(
	edv_context_struct *ctx, const gchar *page_name
);
void EDVWindowAboutDialogMap(edv_context_struct *ctx);


#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)


/*
 *	Checks if the given path is not an absolute path, if it is
 *	not then the current working directory will be prefixed to it.
 *
 *	In addition '~' prefix substitutions will be performed.
 */
static gchar *EDVWindowCopyCompletePath(const gchar *path)
{
	if(ISPATHABSOLUTE(path))
	    return(STRDUP(path));

	/* Home prefix? */
	if(*path == '~')
	{
	    const gchar *home = g_getenv(ENV_VAR_NAME_HOME);
	    if(home == NULL)
		home = "/";
	    return(g_strconcat(home, path + 1, NULL));
	}
	else
	{
	    gchar	*cwd = EDVGetCWD(),
			*dpath = STRDUP(PrefixPaths(cwd, path));
	    g_free(cwd);
	    return(dpath);
	}
}

/*
 *	Executes the command.
 */
static void EDVWindowExec(edv_context_struct *ctx, const gchar *cmd)
{
	if(EDVInterPSGetLock(ctx->cfg_list) > 0)
	    ExecB(cmd);
	else
	    Exec(cmd);
}


/*
 *	Creates a new File Browser.
 */
void EDVWindowBrowserNew(
	edv_context_struct *ctx, const gchar *path
)
{
	const gchar *window_name = "--file-browser";
	gchar *cmd;

	if(ctx == NULL)
	    return;

	if(path != NULL)
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\" \"%s\"",
		ctx->prog_full_path, window_name, path
	    );
	else
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\"",
		ctx->prog_full_path, window_name
	    );
	EDVWindowExec(ctx, cmd);
	g_free(cmd);
}

/*
 *      Creates a new Image Browser.
 */
void EDVWindowImageBrowserNew(
	edv_context_struct *ctx, const gchar *path
)
{
	const gchar *window_name = "--image-browser";
	gchar *cmd;

	if(ctx == NULL)
	    return;

	if(!STRISEMPTY(path))
	{
	    gchar *dpath = EDVWindowCopyCompletePath(path);
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\" \"%s\"",
		ctx->prog_full_path, window_name, dpath
	    );
	    g_free(dpath);
	}
	else
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\"",
		ctx->prog_full_path, window_name
	    );
	EDVWindowExec(ctx, cmd);
	g_free(cmd);
}

/*
 *      Creates a new Archiver.
 */
void EDVWindowArchiverNew(
	edv_context_struct *ctx, const gchar *path
)
{
	const gchar *window_name = "--archiver";
	gchar *cmd;

	if(ctx == NULL)
	    return;

	if(!STRISEMPTY(path))
	{
	    gchar *dpath = EDVWindowCopyCompletePath(path);
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\" \"%s\"",
		ctx->prog_full_path, window_name, dpath
	    );
	    g_free(dpath);
	}
	else
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\"",
		ctx->prog_full_path, window_name
	    );
	EDVWindowExec(ctx, cmd);
	g_free(cmd);
}

/*
 *	Maps the Recycle Bin.
 */
void EDVWindowRecycleBinMap(edv_context_struct *ctx)
{
	const gchar *window_name = "--recycle-bin";
	gchar *cmd;

	if(ctx == NULL)
	    return;

	cmd = g_strdup_printf(
	    "\"%s\" \"%s\"",
	    ctx->prog_full_path, window_name
	);
	EDVWindowExec(ctx, cmd);
	g_free(cmd);
}


/*
 *	Creates a new Properties Dialog and switches to the page 
 *	specified by page_name.
 */
void EDVWindowPropertiesDialogNewWithPage(
	edv_context_struct *ctx, const gchar *path,
	const gchar *page_name
)
{
	const gchar *window_name = "--properties";
	gchar *cmd;

	if(ctx == NULL)
	    return;

	if(!STRISEMPTY(path))
	{
	    gchar *dpath = EDVWindowCopyCompletePath(path);

	    if(!STRISEMPTY(page_name))
		cmd = g_strdup_printf(
		    "\"%s\" \"%s\" \"%s\" \"%s\"",
		    ctx->prog_full_path, window_name, dpath, page_name
		);
	    else
		cmd = g_strdup_printf(
		    "\"%s\" \"%s\" \"%s\"",
		    ctx->prog_full_path, window_name, dpath
		);

	    g_free(dpath);
	}
	else
	{
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\"",
		ctx->prog_full_path, window_name
	    );
	}
	EDVWindowExec(ctx, cmd);
	g_free(cmd);
}

/*
 *	Creates a new Properties Dialog.
 */
void EDVWindowPropertiesDialogNew(
	edv_context_struct *ctx, const gchar *path
)
{
	EDVWindowPropertiesDialogNewWithPage(ctx, path, NULL);
}


/*
 *	Maps the Options Window and switches to the page specified by
 *	page_name.
 */
void EDVWindowOptionsWindowMapWithPage(
	edv_context_struct *ctx, const gchar *page_name
)
{
	const gchar *window_name = "--options";
	gchar *cmd;

	if(ctx == NULL)
	    return;

	if(!STRISEMPTY(page_name))
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\" \"%s\"",
		ctx->prog_full_path, window_name, page_name
	    );
	else
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\"",
		ctx->prog_full_path, window_name
	    );
	EDVWindowExec(ctx, cmd);
	g_free(cmd);
}

/*
 *	Maps the Options Window.
 */
void EDVWindowOptionsWindowMap(edv_context_struct *ctx)
{
	EDVWindowOptionsWindowMapWithPage(ctx, NULL);
}


/*
 *      Maps the Customize Window and switches to the page specified
 *	by page_name.
 */
void EDVWindowCustomizeWindowMapWithTab(
	edv_context_struct *ctx, const gchar *page_name
)
{
	const gchar *window_name = "--customize";
	gchar *cmd;

	if(ctx == NULL)
	    return;

	if(!STRISEMPTY(page_name))
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\" \"%s\"",
		ctx->prog_full_path, window_name, page_name
	    );
	else
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\"",
		ctx->prog_full_path, window_name
	    );
	EDVWindowExec(ctx, cmd);
	g_free(cmd);
}

/*
 *	Maps the Customize Window.
 */
void EDVWindowCustomizeWindowMap(edv_context_struct *ctx)
{
	EDVWindowCustomizeWindowMapWithTab(ctx, NULL);
}


/*
 *	Maps the Devices Window.
 */
void EDVWindowDevicesWindowMap(edv_context_struct *ctx)
{
	const gchar *window_name = "--devices";
	gchar *cmd;

	if(ctx == NULL)
	    return;

	cmd = g_strdup_printf(
	    "\"%s\" \"%s\"",
	    ctx->prog_full_path, window_name
	);
	EDVWindowExec(ctx, cmd);
	g_free(cmd);
}

/*
 *	Maps the MIME Types Wwindow.
 */
void EDVWindowMIMETypesWindowMap(edv_context_struct *ctx)
{
	const gchar *window_name = "--mimetypes";
	gchar *cmd;

	if(ctx == NULL)
	    return;

	cmd = g_strdup_printf(
	    "\"%s\" \"%s\"",
	    ctx->prog_full_path, window_name
	);
	EDVWindowExec(ctx, cmd);
	g_free(cmd);
}


/*
 *	Maps the Run Dialog with the specified command.
 */
void EDVWindowRunDialogMapWithCommand(
	edv_context_struct *ctx, const gchar *command
)
{
	const gchar *window_name = "--run-dialog";
	gchar *cmd;

	if(ctx == NULL)
	    return;

	if(!STRISEMPTY(command))
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\" \"%s\"",
		ctx->prog_full_path, window_name, command
	    );
	else
	    cmd = g_strdup_printf(
	        "\"%s\" \"%s\"",
		ctx->prog_full_path, window_name
	    );
	EDVWindowExec(ctx, cmd);
	g_free(cmd);
}

/*
 *	Maps the Run Dialog.
 */
void EDVWindowRunDialogMap(edv_context_struct *ctx)
{
	EDVWindowRunDialogMapWithCommand(ctx, NULL);
}


/*
 *	Maps the Find Window with the specified location.
 */
void EDVWindowFindWindowMapWithLocation(
	edv_context_struct *ctx, const gchar *location
)
{
	const gchar *window_name = "--find-win";
	gchar *cmd;

	if(ctx == NULL)
	    return;

	if(!STRISEMPTY(location))
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\" \"%s\"",
		ctx->prog_full_path, window_name, location
	    );
	else
	    cmd = g_strdup_printf(
	        "\"%s\" \"%s\"",
		ctx->prog_full_path, window_name
	    );
	EDVWindowExec(ctx, cmd);
	g_free(cmd);
}

/*
 *	Maps the Find Window.
 */
void EDVWindowFindWindowMap(edv_context_struct *ctx)
{
	EDVWindowFindWindowMapWithLocation(ctx, NULL);
}


/*
 *      Maps the About Dialog and switches to the page specified by
 *	page_name.
 */
void EDVWindowAboutDialogMapWithPage(
	edv_context_struct *ctx, const gchar *page_name
)
{
	const gchar *window_name = "--about-dialog";
	gchar *cmd;

	if(ctx == NULL)
	    return;

	if(!STRISEMPTY(page_name))
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\" \"%s\"",
		ctx->prog_full_path, window_name, page_name
	    );
	else
	    cmd = g_strdup_printf(
		"\"%s\" \"%s\"",
		ctx->prog_full_path, window_name
	    );
	EDVWindowExec(ctx, cmd);
	g_free(cmd);
}

/*
 *	Maps the About Dialog.
 */
void EDVWindowAboutDialogMap(edv_context_struct *ctx)
{
	EDVWindowAboutDialogMapWithPage(ctx, NULL);
}
