/*
 * $Id: emenueditor.cpp 2129 2007-11-16 13:03:33Z karijes $
 *
 * Emenueditor, menu editor
 * Part of Equinox Desktop Environment (EDE).
 * Copyright (c) 2000-2006 EDE Authors.
 *
 * This program is licenced under terms of the 
 * GNU General Public Licence version 2 or newer.
 * See COPYING for details.
 */

#include <efltk/Fl_Util.h>
#include <efltk/Fl_Main_Window.h>
#include <efltk/Fl_Images.h>
#include <edeconf.h>

#include "emenueditor.h"
#include "../common/aboutdialog.h"

Fl_Window 	*edit_window = 0;
Fl_FileBrowser  *programs_browser;
Fl_Input        *filename_field, *name_field, *command_field, *icon_field;
int              selected, submenu_selected = 0;
Fl_Input        *filename_field_e, *name_field_e, *command_field_e,*icon_field_e;

void            cb_change_dir(Fl_Widget *, void*);
void            cb_directory_up(Fl_Button *, void*);
void            cb_new_submenu(Fl_Button *, void*);
void            cb_delete_submenu(Fl_Button *, void*);
void            cb_new_item(Fl_Button *, void*);
void            cb_delete_item(Fl_Button *, void*);
void            cb_edit_item(Fl_Button *, void*);
void            cb_about_menu_editor(Fl_Widget*, void*);
void            cbCloseWindow(Fl_Widget*, Fl_Window*);
void            Exit_Editor(Fl_Widget*, void*);
int             SomethingInDir(char *);

void cb_browse(Fl_Widget *, Fl_Input *input)
{
	char *file_types = _("Executables (*.*), *, All files (*.*), *");
	const char *f = fl_select_file(input->value(), file_types, _("File selection ..."));
	if (f) input->value(f);
}


void cb_userMenu(Fl_Widget *, void*)
{
	Fl_String m_programsdir = fl_homedir() + "/.ede/programs";
	programs_browser->directory(m_programsdir);
}

void cb_systemMenu(Fl_Widget *, void*)
{
	fl_alert(_("You need to be root to edit the system menu!"));
	Fl_String m_programsdir = PREFIX"/share/ede/programs";
	programs_browser->directory(m_programsdir);
}

void cb_customMenu(Fl_Widget *, void*)
{
	Fl_String m_programsdir = fl_select_dir(0,  _("Select directory with menu"));
	if (!m_programsdir.empty())
		programs_browser->directory(m_programsdir);
}

static void cb_About(Fl_Item*, void*) {
	AboutDialog("Menu Editor","1.1","");
}



int main(int argc, char **argv)
{
	Fl_String m_programsdir = fl_homedir() + "/.ede/programs";
	fl_init_locale_support("emenueditor", PREFIX"/share/locale");
	fl_init_images_lib();
	
	Fl_Main_Window *menu_edit_window = new Fl_Main_Window(480, 370, _("Menu editor"));
	
	Fl_Menu_Bar *menubar = new Fl_Menu_Bar(0, 0, 480, 25);
	menubar->begin();
		Fl_Item_Group *file = new Fl_Item_Group(_("&File"));
		{
			Fl_Item *o = new Fl_Item(_("&User menu"));
			o->x_offset(18);
			o->callback((Fl_Callback*) cb_userMenu );
		}
		{
			Fl_Item *o = new Fl_Item(_("&System menu"));
			o->x_offset(18);
			o->callback((Fl_Callback*) cb_systemMenu );
		}
		{
			Fl_Item *o = new Fl_Item(_("&Custom..."));
			o->x_offset(18);
			o->callback((Fl_Callback*) cb_customMenu );
		}
		new Fl_Divider();
		{
			Fl_Item *quit_item = new Fl_Item(_("&Quit"));
			quit_item->shortcut(0x40071);
			quit_item->x_offset(18);
			quit_item->callback(Exit_Editor, menu_edit_window);
		}
		file->end();

		Fl_Item_Group *o = new Fl_Item_Group(_("&Help"));
		{
			Fl_Item* o = new Fl_Item(_("&About"));
			o->callback((Fl_Callback*)cb_About);
		}
		//menubar->right_layout(o);
		o->end();

	menubar->end();
	
	programs_browser = new Fl_FileBrowser(5, 40, 275, 313, _("Programs:"));
	programs_browser->align(FL_ALIGN_TOP | FL_ALIGN_LEFT);
	programs_browser->tooltip(_("Click on the submenu or on the item you want"));
	programs_browser->callback(cb_change_dir);
	programs_browser->end();
	programs_browser->directory(m_programsdir);
	menu_edit_window->resizable(programs_browser);
	
	// This group prevents resizing
	{Fl_Group* o = new Fl_Group(310, 45, 135, 313);
		Fl_Button *new_submenu = new Fl_Button(5, 5, 125, 23, _("New submenu"));
		new_submenu->callback( (Fl_Callback*) cb_new_submenu );
		
		Fl_Button *del_submenu =  new Fl_Button(5, 35, 125, 23, _("Delete submenu"));
		del_submenu->callback( (Fl_Callback*) cb_delete_submenu );
		
		Fl_Button *new_item = new Fl_Button(5, 65, 125, 23, _("New item"));
		new_item->callback( (Fl_Callback*) cb_new_item );
		
		Fl_Button *edit_item = new Fl_Button(5, 95, 125, 23, _("Edit Item"));
		edit_item->callback( (Fl_Callback*) cb_edit_item );

		Fl_Button *del_item = new Fl_Button(5, 125, 125, 23, _("Delete item"));
		del_item->callback( (Fl_Callback*) cb_delete_item );
		
		o->end();
	}
	
	menu_edit_window->menu(menubar);
	//menu_edit_window->resizable(menu_edit_window);
	menu_edit_window->end();
	menu_edit_window->show();
	
	Fl::run();
	
	if(edit_window)
		delete edit_window;
	
	return 0;
}


char* get_localized_name(char *cfg)
{
    char *icon_name = 0;
    Fl_Config iconConfig(cfg);
    iconConfig.set_section("Desktop Entry");

    char *alocale = strdup(setlocale(LC_ALL, NULL));
    char *tmp = strrchr(alocale, '_');
    if(tmp)
    {
        *tmp = '\0';
    }
    char localName[1024];
    snprintf(localName, sizeof(localName)-1, "Name[%s]", alocale);
    iconConfig.read((const char *)localName, icon_name);
    delete [] alocale;

    if (!icon_name)
    {
        iconConfig.read("Name", icon_name, "None");
    }

    return icon_name;

}

char* get_localized_string()
{
    char *localname = 0;
    char *alocale = strdup(setlocale(LC_MESSAGES, NULL));
//          -- language_country is perfectly valid according to FD.o
/*    char *tmp = strrchr(alocale, '_');
    if(tmp)
    {
        *tmp = '\0';
    } */
    localname = fl_strdup_printf("Name[%s]", alocale);
    delete [] alocale;

    if (!localname) localname = strdup("Name");
    return localname;
}


void cb_save_item_e(Fl_Widget *, Fl_Window *w)
{
    Fl_String item; 
    Fl_String dir = programs_browser->directory();

    Fl_String name = name_field_e->value();
    if (name.empty())
    {
        fl_alert(_("Please, enter the name of the menu item."));
        return;
    }

    Fl_String filename = filename_field_e->value();
    if (!filename.empty())
	item = filename;
    else
	item = name + ".desktop";

    Fl_String path_and_item = dir + slash + item;
    char *lname = get_localized_string();

    Fl_Config flconfig(path_and_item);
    flconfig.set_section("Desktop Entry");
    flconfig.write(lname, name_field_e->value());
    flconfig.write("Name", name_field_e->value());	// fallback
    flconfig.write("Exec", command_field_e->value());
    flconfig.write("Icon", fl_file_filename(icon_field_e->value()));

    delete [] lname;

    programs_browser->directory(dir);
    programs_browser->relayout();
    w->hide();
}


void cb_browse_icon(Fl_Widget *, Fl_Input *input)
{
    char *file_types = _("Icons (*.png), *.png, All files (*.*), *");
    const char *f = fl_select_file(PREFIX"/share/ede/icons/16x16", file_types, _("Choose icon file..."));
    if (f)
    {
        input->value(f);
    }
}


void Menu_Edit_Dialog(int edit)
{
    if(!edit_window) 
    {
        edit_window = new Fl_Window(370, 250, _("Edit item"));

        filename_field_e = new Fl_Output(5, 25, 195, 23, _("Filename:"));
        filename_field_e->align(FL_ALIGN_TOP | FL_ALIGN_LEFT);

        name_field_e = new Fl_Input(5, 80, 195, 23, _("Name in the menu:"));
        name_field_e->align(FL_ALIGN_TOP | FL_ALIGN_LEFT);

        command_field_e = new Fl_Input(5, 125, 195, 23, _("Command to execute:"));
        command_field_e->align(FL_ALIGN_TOP | FL_ALIGN_LEFT);

        {
            Fl_Button *browse_button_c = new Fl_Button(210, 125, 80, 23, _("Bro&wse..."));
            browse_button_c->callback( (Fl_Callback*) cb_browse, command_field_e );
        }

        icon_field_e = new Fl_Input(5, 215, 195, 23, _("Icon filename:"));
        icon_field_e->align(FL_ALIGN_TOP | FL_ALIGN_LEFT);

        {
            Fl_Button *save_button = new Fl_Button(285, 25, 80, 23, _("&Save"));
            save_button->callback( (Fl_Callback*) cb_save_item_e, edit_window );
        }
        {
            Fl_Button *cancel_button = new Fl_Button(285, 60, 80, 23, _("&Cancel"));
            cancel_button->callback( (Fl_Callback*) cbCloseWindow, edit_window );
        }
        {
            Fl_Button *browse_button_i = new Fl_Button(210, 215, 80, 23, _("&Browse..."));
            browse_button_i->callback( (Fl_Callback*) cb_browse_icon, icon_field_e );
        }
    }

    filename_field_e->value("");
    command_field_e->value("xterm");
    name_field_e->value(_("New folder"));
    icon_field_e->value("item.png");

    if (edit)
    {
        Fl_String c_file = programs_browser->filename_full();
	Fl_String name = programs_browser->filename();
	
	if (!name.empty())
	{
	    char *this_value = 0;
	    filename_field_e->value(name);
	    
            //const char *tfield = filename_field_e->value();

            Fl_Config flconfig(c_file);
            flconfig.set_section("Desktop Entry");

	    this_value = get_localized_name(c_file);
            if(!flconfig.error() && this_value)
	    {
    	        name_field_e->value(this_value);
        	delete [] this_value;
            }
	    flconfig.read("Exec", this_value);
    	    if(!flconfig.error() && this_value)
    	    {
        	command_field_e->value(this_value);
        	delete [] this_value;
    	    }
    	    flconfig.read("Icon", this_value);
    	    if (!flconfig.error() && this_value)
    	    {
        	icon_field_e->value(this_value);
        	delete [] this_value;
    	    }
	}    
    }

    edit_window->end();
    edit_window->exec();
}

void cb_new_submenu(Fl_Button *, void *)
{
    Fl_String m_progdir = programs_browser->directory();
    Fl_String m_submenu = fl_input(_("Please enter name of the new submenu:"));
    
    if (!m_submenu.empty())
    {
	Fl_String path = m_progdir + slash + m_submenu;
        if (mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR))
        {
            fl_alert(_("Cannot create submenu!"));
            return;
        }
    }
    programs_browser->directory(m_progdir);
    programs_browser->relayout();
    programs_browser->redraw();    
}

void cb_change_dir(Fl_Widget *w, void  *)
{
    if(Fl::event_clicks() || Fl::event_key() == FL_Enter) {
        Fl_String path_name(programs_browser->filename_full());

        if(path_name.empty()) {
            programs_browser->up();
            return;
        }

        if(fl_is_dir(path_name)) {

            programs_browser->load(path_name);
            programs_browser->redraw();

        } else {

            Menu_Edit_Dialog(1);

        }
    }
}

void cb_directory_up(Fl_Button *, void *)
{
    programs_browser->up();
}

int SomethingInDir(char *path)
{
    dirent **files;
    int numberOfFiles = 0;

    numberOfFiles = fl_filename_list(path, &files);

    if (numberOfFiles > 2)       // . | .. | +
    {
        for (int i = 0; i < numberOfFiles; i ++)
        {
            free(files[i]);
        }
        free(files);
        return numberOfFiles;
    }
    else
    {
        return 0;
    }
}

void cb_delete_submenu(Fl_Button *, void*)
{
    Fl_String submenu_path(programs_browser->filename_full());
    if (fl_file_exists(submenu_path) && fl_is_dir(submenu_path))
    {
        if (SomethingInDir(submenu_path))
        {
            fl_alert(_("You should delete all the items from the submenu, before you can delete it!"));
            return;
        }
        rmdir(submenu_path);
        programs_browser->directory(programs_browser->directory());
        programs_browser->redraw();
    }
}

void cb_delete_item(Fl_Button *, void *)
{
    Fl_String submenu_path(programs_browser->filename_full());
    if(fl_file_exists(submenu_path) && !fl_is_dir(submenu_path))
    {
        unlink(submenu_path);
        programs_browser->directory(programs_browser->directory());
        programs_browser->redraw();
    }
}

void cb_new_item(Fl_Button *, void *)
{
    Menu_Edit_Dialog(0);
    programs_browser->redraw();
}

void cb_edit_item(Fl_Button *, void *)
{
    Fl_String submenu_path(programs_browser->filename_full());
    if(!fl_is_dir(submenu_path))
    {
       Menu_Edit_Dialog(1);
       programs_browser->redraw();
    }
}

void cbCloseWindow(Fl_Widget *, Fl_Window *windowToClose)
{
    windowToClose->hide();
}

void Exit_Editor(Fl_Widget *w, void *d)
{
    Fl_Window *t = (Fl_Window*) d;
    t->hide();
}
