/*
  Cloned Xunzip
  Copyright (C) 1999 Tero Koskinen

  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 2 of the License, or
  (at your option) any later version.

  This program 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, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
*/

#include <stdio.h>
#include <unistd.h>
#include <config.h>

#include <string>

#include <glib.h>
#include <gnome.h>

#include "app.hh"
#include "prefs.hh"
#include "prepareapp.hh"
#include "callbacks.hh"
#include "uncompresswindow.hh"

#include "zip_wrapper.h"

namespace 
{
        std::string escapeChars(const std::string & name)
        {
                std::string tmp;

                for (unsigned int index = 0; index < name.size(); ++index)
                {
                        char etable[] = " \\\'\"><&;()[]";
                        for (unsigned int a = 0;a < sizeof(etable); ++a)
                        {
                                if (name[index] == etable[a])
                                {
                                        tmp += "\\";
                                        break;
                                }
                        }
                        tmp += name[index];
                }
	
                return tmp;
        }
}


void app_quit(GtkWidget* w, App *app)
{
	if (app) {
		app->write_config();
		delete app;
	} else {
	        fprintf(stderr, "No app found, options not saved!\n");
        }
	gtk_main_quit();
}

void de_app_quit(GtkWidget *widget, GdkEvent *event, gpointer data)
{
        App* app = reinterpret_cast<App*>(data);
        
	if (app) {
		app->write_config();
		delete app;
	} else {
	        fprintf(stderr, "No app found, options not saved!\n");
        }
	gtk_main_quit();
}

void cancel_callback(GtkWidget *,GtkWidget **w)
{
	if (w && *w)  {
		gtk_widget_hide(*w);
		gtk_widget_destroy(*w);
		*w=NULL;
	}
}

void create_file_selection_callback(GtkWidget *,App *app)
{
	g_return_if_fail(app!=NULL);
	
	app->filesel = gtk_file_selection_new (_("File selection"));
	gtk_window_position (GTK_WINDOW (app->filesel), GTK_WIN_POS_MOUSE);
	gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (app->filesel)->ok_button),
			    "clicked", (GtkSignalFunc) open_file_callback,
			    app);
	gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (app->filesel)->cancel_button),
			    "clicked", (GtkSignalFunc) cancel_callback,
			    &app->filesel);
	gtk_widget_show(app->filesel);
}

void open_file_callback(GtkWidget *,App *app)
{
	gchar *file;
	
	g_return_if_fail(app!=NULL);
	g_return_if_fail(app->filesel!=NULL);
	
	file=gtk_file_selection_get_filename (GTK_FILE_SELECTION (app->filesel));
	open_file(file,app);
	destroy_file_selection(app);

}

void uncompress_file_callback(GtkWidget *,App *app)
{
	create_uncompress_dialog(app);
}

void select_list_row_callback(GtkCList *,gint row,gint,
			      GdkEventButton *,App *app)
{
	app->selectedFile=row;
}

void unselect_list_row_callback(GtkCList *,gint ,gint,
			      GdkEventButton *,App *app)
{
	app->selectedFile=-1;
}

void dialog_uncompress_callback(GtkWidget *,App *app)
{
	gchar *file;
	int status=0;
	int extra_flags=0;

	g_return_if_fail(app != NULL);
	g_return_if_fail(app->dialog != NULL);
	g_return_if_fail(app->dialog_entry != NULL);

	extra_flags=0x02*gtk_toggle_button_get_active(
		GTK_TOGGLE_BUTTON(app->dialog_lcase_names_button));

	file=gnome_file_entry_get_full_path(
		GNOME_FILE_ENTRY(app->dialog_entry),0);

	if (file) {
		if (app->oneFile!=0 && app->selectedFile!=-1) {
			status=zip_file_uncompress_nth(app->selectedFile+1,
						       file,app->zip,
						       extra_flags);
		}
		else if (app->oneFile == 0) {
			status=zip_file_uncompress_all(file,app->zip,
						       extra_flags);
		} else {
			status = 1;
			show_error(_("Please select a file!\n"));
		}


		if (status==0)
			show_error(_("Uncompression error"));
		gnome_dialog_close(GNOME_DIALOG(app->dialog));
		app->dialog=0;
	}
}

void selected_file_toggled_callback(GtkWidget *,App *app)
{
	g_return_if_fail(app!=NULL);
	
	app->oneFile=!app->oneFile;
}

void test_archive_callback(GtkWidget *,App *app)
{
	int status=0;
	GSList *errors;
	
	g_return_if_fail(app!=NULL);

	if (app->zip == NULL || app->zip->opened == 0)
                return;
	
	gnome_appbar_push(GNOME_APPBAR(app->bar),
			  _("Testing...please wait..."));

	errors=zip_file_test(app->zip,&status);

	if (status==0)
		list_errors(errors); /* printf("Errors...\n"); */
	else
		show_message(_("No errors"));
	
	gnome_appbar_pop(GNOME_APPBAR(app->bar));
}

void view_callback(GtkWidget *,App *app)
{
	if (app->selectedFile>-1) {
		create_view_dialog(app);
	}
}

void view_dialog_clicked_callback(gchar *cmdstring,App *app)
{
	pid_t pid=0;
	char *msg;
	int status=0;
	const char *dirname=NULL;
	char *filename=NULL;
	GSList *node;
	ZipCDR *cdr;

	g_return_if_fail(app!=NULL);

	if (cmdstring) {
		if (app->tmpdir.size() == 0) {
			pid=getpid();
			msg=g_strdup_printf("/tmp/%d.cxunzip.XXXXXX",(int)pid);
			dirname=mkdtemp(msg);
			app->tmpdir = dirname;
			g_free(msg);
		} else
			dirname=app->tmpdir.c_str();
		
		node=g_slist_nth(app->zip->records,app->selectedFile+1);
		cdr=(ZipCDR*)node->data;
		filename=cdr->filename;
		
		status=zip_file_uncompress_nth(app->selectedFile+1,
					       dirname,app->zip,1);
		if (status==0) {
			msg=g_strdup_printf(_("Unable view file %s"),filename);
			show_error(msg);
		} else {
                        std::string fname = escapeChars(filename);
			msg=g_strdup_printf("%s %s/%s &",
					    cmdstring,dirname,fname.c_str());
			system(msg);
		}
		g_free(msg);
	}
}

void about_callback(GtkWidget *,App *)
{
	const gchar *authors[]= { "Tero Koskinen <tkoskine@students.cc.tut.fi>",NULL };
	GtkWidget *about=gnome_about_new("Cloned Xunzip",
					 VERSION,
					 _("Copyright (C) 2000-2003 Tero Koskinen"),
					 authors,
					 _("Cloned Xunzip Homepage\nhttp://gurb.ton.tut.fi/gnome/"),
					 NULL);
	gtk_widget_show(about);
}

void preferences_callback(GtkWidget *,App *app)
{
	g_return_if_fail(app!=NULL);

	create_preferences(app);
}

void dnd_drop_callback(GtkWidget * /* w */ ,
		       GdkDragContext * /* context */ ,
		       gint /* x */,gint /* y */,
		       GtkSelectionData *selection_data ,
		       guint /* info */,
		       guint /* time */,
		       App *app )
{
	/* printf("dnd_drop\n"); */
	
	if (selection_data) {
		if (selection_data->data) {
			open_file((char*)selection_data->data,app);
		}
	}
} 

void dnd_drag_callback(GtkWidget        * /* widget */,
		       GdkDragContext   * /* context */,
		       GtkSelectionData *selection_data,
		       guint             info,
		       guint             /* time */,
		       App *app)
{
	char *filename=NULL;
	GSList *node;
	ZipCDR *cdr;
	int status=0;

	node=g_slist_nth(app->zip->records,app->selectedFile+1);
	cdr=(ZipCDR*)node->data;
/*	filename=g_strdup_printf("%s/%s",app->tmpdir,cdr->filename); */
	status=zip_file_uncompress_nth(app->selectedFile+1,
				       app->tmpdir.c_str(),app->zip,1);
	if (status==0)
		return;

	switch(info) {
	case TARGET_TEXT_PLAIN:
		/* g_print("TARGET_TEXT_PLAIN\n"); */
		filename=g_strdup_printf("%s/%s",app->tmpdir.c_str(),
                                         cdr->filename);
		gtk_selection_data_set(selection_data,
				       selection_data->target,8,
				       (unsigned char*)filename,strlen(filename));
		selection_data->type=gdk_atom_intern("text/plain",FALSE);
		break;
	case TARGET_URI_LIST:
		/* g_print("TARGET_URI_LIST\n"); */
		filename=g_strdup_printf("file:%s/%s\r\n%c",
                                         app->tmpdir.c_str(),
                                         cdr->filename,'\0');
		gtk_selection_data_set(selection_data,
				       selection_data->target,8,
				       (unsigned char*)filename,strlen(filename));
		selection_data->type=gdk_atom_intern("text/uri-list",FALSE);

		break;
	default:
		g_print("DND: unsupported type!\n");
		break;
	}
	if (filename)
		g_free(filename);
}

void toggled_pBtn1_callback(GtkWidget *,App *app)
{
	app->saveSizeTmp=!app->saveSizeTmp;
}

void apply_prefs_callback(GtkWidget *,gint ,App *app)
{
	g_return_if_fail(app!=NULL);
	
	app->saveSize=app->saveSizeTmp;
}
