
/* Gnome Encfs Manager (GEncfsM)
 * Copyright (C) 2011 Moritz Molch <mail@moritzmolch.de>
 
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

using Encfs;
using Gtk;
using Gee;
using GnomeEncfsManager;
using Secret;
using GLib;

namespace GnomeEncfsManager {
    public class ConfigureStash {
        private static Window window;
        private static Builder builder;
        private static Entry entry_mount_dir;
        
        private static Stash stash;
        private static ConfigureStashAdvanced adv_dialog;

        public static void show(Stash s) {
            if ((window != null) || (s == null))
                return;
        
            try {
                builder = new Builder();
                builder.add_from_file(get_glade_file("configure_stash.ui"));
                builder.connect_signals(null);
                window = (Window)builder.get_object("configure");
                entry_mount_dir = (Entry)builder.get_object("entry_mount_dir");
                
                stash = s;
                
                update();
                ((CheckButton)builder.get_object("checkbutton_mount_on_startup")).grab_focus();

                ((Window)window).present();
                ((Window)window).set_keep_above(true);

            } catch (GLib.Error e) {
                stderr.printf("Could not load UI: %s\n", e.message);
            }
        }
        
        public static void hide() {
            if (window == null)
                return;

            save_stashes();
            window.destroy();
            stash = (Stash)null;
            window = (Window)null;
            MountDialog.update();
        }
        
        public static void kill() {
            if (window == null)
                return;

			if (adv_dialog != null)
				adv_dialog.destroy();

            window.destroy();
            stash = (Stash)null;
            window = (Window)null;
        }
        
        public static void update() {
            if ((window == null) || (stash == null))
                return;
            
            entry_mount_dir.text = stash.mountDir;
            entry_mount_dir.set_sensitive(!stash.isMounted);
            
            ((CheckButton)builder.get_object("checkbutton_mount_on_startup")).set_active(stash.autoMount);
            ((CheckButton)builder.get_object("checkbutton_mount_when_available")).set_active(stash.mountWhenAvailable);
            ((CheckButton)builder.get_object("checkbutton_allow_other")).set_active(stash.allowOther);
            ((CheckButton)builder.get_object("checkbutton_unmount_when_idle")).set_active(stash.unmountWhenIdle);
            
            ((SpinButton)builder.get_object("spinbutton_idle_unmount_time")).set_value(stash.idleTimeout);
            ((CheckButton)builder.get_object("checkbutton_keep_mount_directory")).set_active(stash.options.get_bool("keep_mount_directory"));
            
            ((CheckButton)builder.get_object("checkbutton_open_filemanager")).set_active(stash.options.get_bool("open_file_manager"));
            ((CheckButton)builder.get_object("checkbutton_use_keyring")).set_active(stash.useKeyring);
            ((CheckButton)builder.get_object("checkbutton_tray_menu")).set_active(stash.showInTrayMenu);
        }
        
        public static void timeout_changed(SpinButton source) {
            stash.idleTimeout = (int)source.get_value();
        }
        
        public static void idle_unmount_toggled(CheckButton source) {
            stash.unmountWhenIdle = source.get_active();
        }
        
        public static void keep_mount_directory_toggled(CheckButton source) {
            stash.options.set_bool("keep_mount_directory", source.get_active());
            if (stash.isMounted || stash.isMounting) {
                return;
            }
            
            if (source.get_active()) {
                if (!FileUtils.test(stash.mountDir, FileTest.IS_DIR)) {
                    try {
                        string exit_stderr;
                        int exit_status;
	                    Process.spawn_command_line_sync( "mkdir -m 700 -p \""+stash.mountDir+"\"" , null, out exit_stderr, out exit_status );
	                }
	                catch (GLib.Error e) {}
	            }
            } else {
                if (FileUtils.test(stash.mountDir, FileTest.IS_DIR)) {
                    Posix.rmdir(stash.mountDir);
                }
            }
        }
        
        public static void available_toggled(CheckButton source) {
            stash.mountWhenAvailable = source.get_active();
        }
        
        public static void startup_toggled(CheckButton source) {
            stash.autoMount = source.get_active();
        }
        
        public static void allow_other_toggled(CheckButton source) {
        	if (stash.allowOther == source.get_active()) return;
        	
        	if (source.get_active()) {
        		source.set_active(false);
        		if (user_allow_other_enabled()) {
        			stash.allowOther = (true);
        			update();
        		}
        		else {
        			InformationDialog.show_message(_("Allow other users to access this stash"), _("Please enable the option \"user_allow_other\" in the file \"/etc/fuse.conf\" and make sure that the file is readable by you."));
        		}
        	}
	        else {
				stash.allowOther = source.get_active();
			}
        }
        
        private static bool user_allow_other_enabled() {
        	string filename = "/etc/fuse.conf";
        	string contents = null;
        	try {
	        	FileUtils.get_contents(filename, out contents);

	        	var regex = new Regex("""\n\ *user_allow_other""", RegexCompileFlags.EXTENDED);
	        	return regex.match(contents);
            } catch (GLib.Error e) {
                return false;
            }
        }
        
        public static void keyring_toggled(CheckButton source) {
            stash.useKeyring = source.get_active();
            if (!source.get_active()) {
				Secret.password_clear_sync(Secret.get_schema(Secret.SchemaType.COMPAT_NETWORK), null, "server", stash.cryptDir);
            }
        }
        
        public static void filemanager_toggled(CheckButton source) {
            stash.options.set_bool("open_file_manager", source.get_active());
        }
        
        public static void traymenu_toggled(CheckButton source) {
            stash.showInTrayMenu = source.get_active();
            TrayIcon.update();
        }
        
        public static void mount_dir_changed() {
			string output;
			stash.changeMountDir(entry_mount_dir.text, out output);
		    MountDialog.update();
		    Manager.update();
		    TrayIcon.update();
        }
        
        public static void show_advanced_dialog() {
			adv_dialog = new ConfigureStashAdvanced();
			adv_dialog.set_stash(stash);
            ((Window)adv_dialog).present();
            ((Window)adv_dialog).set_keep_above(true);
			adv_dialog.run();
			adv_dialog = (ConfigureStashAdvanced)null;
        }
        
        public static void show_filechooser_mount_dir() {
        	FileChooserDialog dialog = new FileChooserDialog(_("Please select the mount folder"), window,
        													 FileChooserAction.SELECT_FOLDER,
        													 Stock.CANCEL, ResponseType.CANCEL,
        													 Stock.OPEN, ResponseType.ACCEPT);
        													 
			dialog.set_filename(stash.mountDir);
			dialog.set_local_only(false);
			dialog.set_modal(true);
        	dialog.show();
        	dialog.response.connect( (dlg, response_id) => {
        		if (response_id == ResponseType.ACCEPT) {
	        		entry_mount_dir.text = dialog.get_filename();
					mount_dir_changed();
	        	}
        		dialog.hide();
        	});
        }
    }
    
    public class ConfigureStashAdvanced : Dialog {
    	public const string options[] = {   "encfs_bin",
    						 				"encfsctl_bin",
    						 				"fusermount_bin",
									 		"additional_encfs_options",
											"pre_mount_command",
											"post_mount_command",
											"pre_unmount_command",
											"post_unmount_command",
											"keyring_name"
    					   		 		};
		Stash stash;
		private HashMap<string, Entry> entries;
		private Entry entry_encfs_config;
		
		
		//Entry entries[];
    					   		 
		public ConfigureStashAdvanced() {
			this.title = _("Advanced stash configuration");
			this.border_width = 5;
			set_default_size (100, 100);
			create_widgets ();
			connect_signals ();
		}

		private void create_widgets () {
			entries = new HashMap<string, Entry> ();
		
			Grid grid = new Grid();
			
			var label = new Label("<a href=\"http://moritzmolch.com/1291\">" + _("Please visit this link to learn about GEncfsM scripts and scripting.") + "</a>");
			label.use_markup = true;
			label.set_line_wrap (true);
			label.xalign = 0;
			label.ypad = 5;
			label.margin_bottom = 8;
			grid.attach(label, 0,0,2,1);
			
			label = new Label("encfs_config_file:");
			label.xalign = 0;
			entry_encfs_config = new Entry();
			grid.attach(label, 0,1,1,1);
			grid.attach(entry_encfs_config, 1,1,1,1);
			
			int i = 2;
			foreach (string s in options) {
				label = new Label(s + ":");
				label.xalign = 0;
				label.margin_right = 5;
				var entry = new Entry();
				entries[s] = entry;
				grid.attach(label, 0,i,1,1);
				grid.attach(entry, 1,i,1,1);
				i++;
			}
		

			Gtk.Box content = get_content_area () as Gtk.Box;
			content.spacing = 10;
			content.pack_start (grid, false, true, 0);

			add_button (Gtk.Stock.CLOSE, Gtk.ResponseType.CLOSE);
			this.show_all();
		}

		private void connect_signals () {
			this.response.connect (on_response);
		}

		private void on_response (Gtk.Dialog source, int response_id) {
			stash.encfs6config = entry_encfs_config.get_text();
			//stash.options.clear();
			foreach (var entry in entries.entries) {
				stash.options.set_string(entry.key, entry.value.get_text());
			}
			destroy();
		}
		
		private void update() {
			entry_encfs_config.set_text(stash.encfs6config);
			foreach (var entry in entries.entries) {
				entries[entry.key].set_text(stash.options.get_string(entry.key));
			}
		}
		
		public void set_stash(Stash stash) {
			this.stash = stash;
			update();
		}
    }
}
