/* $Id: e2p_pack.c 706 2007-11-06 09:13:06Z tpgww $

Copyright (C) 2003-2007 tooar <tooar@gmx.net>
Portions copyright (C) 1999 Michael Clark

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
*/

/**
@file plugins/e2p_pack.c
@brief plugin for interfacting with several archive managers, to pack selected item(s)
*/

#include "emelfm2.h"
#include <string.h>
#include "e2_plugins.h"
#include "e2_dialog.h"
#include "e2_command.h"
#include "e2_task.h"
#include "e2_filelist.h"
//same enum as in unpack plugin
enum { TAR_GZ, TAR_BZ2, TAR, ZIP, Z7Z, RAR, ARJ, ZOO, MAXTYPES };

typedef struct _E2_PackDlgRunTime
{
	GtkWidget *dialog;
	GtkWidget *filename_entry;
	GtkWidget *pkgtype_combo;
	gchar *curr_dir;	//utf8 form of qed->currdir (with trailer)
} E2_PackDlgRunTime;

static gint pkg_type = TAR_GZ;	//in theory, we should protect this by mutex

//these extension strings are in same order as enum
//CHECKME do these really need to be translated ?
static gchar *ext_str [MAXTYPES] =
{
	N_(".tar.gz"),
	N_(".tar.bz2"),
	N_(".tar"),
	N_(".zip"),
	N_(".7z"),
	N_(".rar"),
	N_(".arj"),
	N_(".zoo")
};

static gboolean _e2p_packQ (E2_ActionTaskData *qed);

static void _e2p_pack_yes (E2_PackDlgRunTime *rt)
{
	static gchar *cmd_str [MAXTYPES] =
	{	//these command strings are in same order as enum
		//NOTE that %%f is converted to %f when the command is constructed with g_strdup_printf ()
		">tar cvf - %%f | gzip - > \"%s\"",	//run in separate shell
		">tar cvf - %%f | bzip2 - > \"%s\"",	//ditto
		"tar cvf \"%s\" %%f",
		"zip -r \"%s\" %%f",
		"7za a -t7z \"%s\" %%f",
		"rar a -r -ol \"%s\" %%f",
		"arj a -a1 -r \"%s\" %%f",
		"zoo ahP \"%s\" %%f"
	};
/*
compress ANSI files: 7za a -tzip archive.zip file1 file2 ... fileN
compress ANSI dir:   7za a -tzip archive.zip dirnametocompress\
compress UNICODE files: 7za a -t7z archive.7z file1 file2 ... fileN
compress UNICODE dir:   7za a -t7z archive.7z dirnametocompress\
decompress ANSI:    7za x archive.zip -odirname -aoa
decompress UNICODE: 7za x archive.7z -odirname -aoa
*/
	pkg_type = gtk_combo_box_get_active (GTK_COMBO_BOX (rt->pkgtype_combo));
	if (pkg_type != -1)
	{
		gchar *full_name;
		const gchar *chosen_name = gtk_entry_get_text (GTK_ENTRY (rt->filename_entry));
		gboolean flag = (*chosen_name != '\0');
		if (flag)
		{
			full_name = g_strconcat (chosen_name, ext_str [pkg_type], NULL);

			if (e2_option_bool_get ("confirm-overwrite"))
			{
#ifdef E2_VFSTMP
				//FIXME dir when not mounted local
#else
				gchar *utf = g_strconcat (rt->curr_dir, full_name, NULL);  //separator comes with dir
#endif
				gchar *dlocal = F_FILENAME_TO_LOCALE (utf);
#ifdef E2_VFS
				VPATH ddata = { dlocal, NULL };	//running a command is only local
				if (e2_fs_access2 (&ddata E2_ERR_NONE()) == 0)
#else
				if (e2_fs_access2 (dlocal E2_ERR_NONE()) == 0)
#endif
				{	//same-named item exists already
					//FIXME some apps allow addition to existing archive
					DialogButtons result = e2_dialog_ow_check (NULL, dlocal, NONE);
					if (result != OK)
					{
						flag = FALSE;	//signal that we will not proceed
						g_free (full_name);
					}
				}
				g_free (utf);
				F_FREE (dlocal);
			}
		}

		if (flag)
		{
			gchar *command =  g_strdup_printf (cmd_str [pkg_type], full_name);
//			e2_filelist_disable_refresh ();	//prevent changes to selected item data
//			gint res =
#ifdef E2_COMMANDQ
			e2_command_run (command, E2_COMMAND_RANGE_DEFAULT, FALSE);
#else
			e2_command_run (command, E2_COMMAND_RANGE_DEFAULT);
#endif
//			e2_filelist_enable_refresh (); //probably nothing reported yet, to trigger a refresh
//			flag = (res == 0);
			g_free (command);
			g_free (full_name);
		}
	}
	else
		pkg_type = TAR_GZ;
}
/**
@brief callback for dialog's "response" signal

@param dialog the dialog where the response was triggered
@param response the response for the clicked button
@param rt pointer to data for dialog

@return
*/
static void _e2p_pack_response_cb (GtkDialog *dialog, gint response,
	E2_PackDlgRunTime *rt)
{
	switch (response)
	{
		case GTK_RESPONSE_OK:
			gtk_widget_hide (rt->dialog);
			_e2p_pack_yes (rt);
			break;
		default:
			break;
	}
	gtk_widget_destroy (rt->dialog);
	g_free (rt->curr_dir);
	DEALLOCATE (E2_PackDlgRunTime, rt);
}
/**
@brief handle activation (<Return> keypresses) in the query entry

@param entry UNUSED the entry widget for the combo box
@param rt pointer to dialog data struct
@return
*/
static void _e2p_pack_activated_cb (GtkEntry *entry, E2_PackDlgRunTime *rt)
{
	_e2p_pack_response_cb (GTK_DIALOG (rt->dialog), GTK_RESPONSE_OK, rt);
}
/**
@brief create and run dialog

@param from the button, menu item etc which was activated
@param art action runtime data

@return TRUE if action completed successfully, else FALSE
*/
static gboolean _e2p_pack (gpointer from, E2_ActionRuntime *art)
{
	return (e2_task_enqueue_task (E2_TASK_PACK, art, from, _e2p_packQ, NULL));
}
static gboolean _e2p_packQ (E2_ActionTaskData *qed)
{
	E2_PackDlgRunTime *rt = ALLOCATE (E2_PackDlgRunTime);
	CHECKALLOCATEDWARNT (rt, return FALSE;)

	rt->dialog = e2_dialog_create (NULL, _("Filename:"),
		_("archive creation"), _e2p_pack_response_cb, rt);

	GtkWidget *hbox = g_object_get_data (G_OBJECT (rt->dialog), "e2-dialog-hbox");

	GPtrArray *names = qed->names;
	E2_SelectedItemInfo **iterator = (E2_SelectedItemInfo **) names->pdata;
	gchar *suggested_name = F_FILENAME_FROM_LOCALE ((*iterator)->filename);
	rt->filename_entry = e2_widget_add_entry (hbox, suggested_name, TRUE, TRUE);
	F_FREE (suggested_name);
#ifdef E2_ASSISTED
	GtkWidget *label = (GtkWidget *) g_object_get_data (G_OBJECT (rt->dialog),
		"e2-dialog-label");
	e2_widget_set_label_relations (GTK_LABEL (label), rt->filename_entry);
#endif

	rt->pkgtype_combo = e2_combobox_add (hbox, TRUE, 0, NULL, NULL, NULL,
		E2_COMBOBOX_MENU_STYLE);
	g_signal_connect (G_OBJECT (rt->filename_entry), "activate",
		G_CALLBACK (_e2p_pack_activated_cb), rt);

	//these package name strings are in same order as enum
	//CHECKME do these really need to be translated ?
/*	gchar *type_choices [MAXTYPES] = { _(".tar.gz"),  //index 0
		_(".tar.bz2"), _(".tar"), _(".zip"), _(".7z"), _(".rar"),
		_(".arj") _(".zoo")};  //index 6
	e2_combobox_append_history_counted (rt->pkgtype_combo, MAXTYPES, type_choices);
*/
	guint i;
	for (i = 0; i < MAXTYPES; i++)
		gtk_combo_box_append_text (GTK_COMBO_BOX (rt->pkgtype_combo),
			gettext (ext_str[i]));

	gtk_combo_box_set_active (GTK_COMBO_BOX (rt->pkgtype_combo), pkg_type);

	rt->curr_dir = D_FILENAME_FROM_LOCALE (qed->currdir);

	gdk_threads_enter ();
	e2_dialog_show (rt->dialog, app.main_window, 0, &E2_BUTTON_CANCEL,
		&E2_BUTTON_OK, NULL);
	gdk_threads_leave ();
	return TRUE;
}

//aname must be confined to this module
static gchar *aname;
/**
@brief plugin initialization function, called by main program

@param p ptr to plugin data struct

@return TRUE if the initialization succeeds, else FALSE
*/
gboolean init_plugin (Plugin *p)
{
#define ANAME "pack"
	aname = _("pack");

	p->signature = ANAME VERSION;
	p->menu_name = _("_Pack..");
	p->description = _("Build an archive containing the selected item(s)");
	p->icon = "plugin_"ANAME"_"E2IP".png";  //use icon file pathname if appropriate

	if (p->action == NULL)
	{
		//no need to free this
		gchar *action_name = g_strconcat (_A(5),".", aname, NULL);
		p->action = e2_plugins_action_register
			(action_name, E2_ACTION_TYPE_ITEM, _e2p_pack, NULL, FALSE, 0, NULL);
		return TRUE;
	}
	return FALSE;
}
/**
@brief cleanup transient things for this plugin

@param p pointer to data struct for the plugin

@return TRUE if all cleanups were completed
*/
gboolean clean_plugin (Plugin *p)
{
	gchar *action_name = g_strconcat (_A(5),".",aname,NULL);
	gboolean ret = e2_plugins_action_unregister (action_name);
	g_free (action_name);
	return ret;
}
