// Emacs style mode select -*- C++ -*-
//------------------------------------------------------------------------
//
// Copyright(c) 2001, 2002 Simon Howard
//
// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
//------------------------------------------------------------------------
//
// GTK+ Interface
//
//------------------------------------------------------------------------

#include <stdio.h>
#include <gtk/gtk.h>
#include "parse.h"
#include "scan.h"

extern int g_argc;
extern char **g_argv;

typedef struct {
	GtkWidget *treeitem;
	GtkWidget *subtree;
	GtkWidget *label;
        GtkWidget *textlabel;         // label: save so we can change color
} gtkdata_t;

static char *os_icon_filenames[MACHINE_TYPES] = {
        DATADIR "/unix.xpm",             // MACHINE_UNIX
        DATADIR "/linux.xpm",            // MACHINE_LINUX
        DATADIR "/win.xpm",              // MACHINE_WIN
        DATADIR "/machine.xpm",          // MACHINE_CHECKUP
};
static GdkPixmap *os_icons[MACHINE_TYPES] = {NULL};
static GdkBitmap *os_icon_masks[MACHINE_TYPES];

static GdkPixmap *user_icon;
static GdkBitmap *user_icon_mask;

static GtkWidget *window;
static GtkWidget *statusbar;

#ifdef CSLIB

// load cslib logo

static GtkWidget *load_cslib_logo()
{
	GdkPixmap *logo;
	GdkBitmap *mask;
	GtkStyle *style = gtk_widget_get_style(window);

	logo = gdk_pixmap_create_from_xpm
		(window->window, &mask, 
		 &style->bg[GTK_STATE_NORMAL], 
		 DATADIR "/cslib.xpm");
	
	return gtk_pixmap_new(logo, mask);
}

#endif /* #ifdef CSLIB */

// get label for a particular machine

static GtkWidget *get_machine_label(machine_t *machine)
{
	GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
	GtkWidget *machine_type;		
	GtkWidget *label = gtk_label_new(machine->hostname);

	if(!os_icons[0]) {
		GtkStyle *style = gtk_widget_get_style(window);
                int i;

                for(i=0; i<MACHINE_TYPES; ++i) {
                        os_icons[i] = 
                                gdk_pixmap_create_from_xpm
                                (window->window, 
                                 &os_icon_masks[i],
                                 &style->bg[GTK_STATE_NORMAL],
                                 os_icon_filenames[i]);
                        if(!os_icons[i]) {
                                fprintf(stderr,
                                        "get_machine_label: Can't load '%s'\n",
                                        os_icon_filenames[i]);
                        }
                }
                
                user_icon = 
                        gdk_pixmap_create_from_xpm
                        (window->window, 
                         &user_icon_mask,
                         &style->bg[GTK_STATE_NORMAL],
                         DATADIR "/user.xpm");
	}

        machine_type = gtk_pixmap_new(os_icons[machine->type], 
                                      os_icon_masks[machine->type]);

	gtk_box_pack_start (GTK_BOX (hbox),
			    machine_type, 
			    FALSE, FALSE, 3);
	
	gtk_box_pack_start (GTK_BOX (hbox), 
			    label, 
			    FALSE, FALSE, 3);

	gtk_widget_show(machine_type);
	gtk_widget_show(label);

        ((gtkdata_t *) machine->interface_data)->label = hbox;
        ((gtkdata_t *) machine->interface_data)->textlabel = label;

	return hbox;
}

// create a page for a particular cluster

static GtkWidget *create_cluster_page(cluster_t *cluster)
{
	// create various objects
	
	GtkWidget *page = gtk_frame_new("Machines");
	GtkWidget *scrollwin = gtk_scrolled_window_new(NULL, NULL);
	GtkWidget *tree = gtk_tree_new();

	int m;

	// always a vertical scrollbar, not always horiz.
	
	gtk_scrolled_window_set_policy
		(GTK_SCROLLED_WINDOW (scrollwin),
		 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);

	// put the tree in the scrollwin
	
	gtk_scrolled_window_add_with_viewport
		(GTK_SCROLLED_WINDOW(scrollwin), tree);

	// put scrollwin on the page
	
	gtk_container_add(GTK_CONTAINER(page), scrollwin);

        gtk_tree_set_view_lines(GTK_TREE(tree), 0);
	
	// add machines to tree
	
	for(m=0; m<cluster->num_machines; m++) {
		machine_t *machine = cluster->machines[m];
		GtkWidget *label = get_machine_label(machine);
		
		// create a menuitem for this machine

		GtkWidget *item
			= gtk_tree_item_new();

		// add label

		gtk_container_add (GTK_CONTAINER(item), label);


		// add to tree
		
		gtk_tree_append(GTK_TREE(tree), item);

		// create subtree

		((gtkdata_t *)machine->interface_data)->treeitem = item;
		((gtkdata_t *)machine->interface_data)->subtree = NULL;

		// show

		//gtk_widget_show(label);		
		gtk_widget_show(item);
	}
	
	// show em all
	
	gtk_widget_show(tree);
	gtk_widget_show(scrollwin);
	gtk_widget_show(page);	

	return page;
}

void ui_init()
{
	GtkWidget *vbox, *action_area;
	GtkWidget *notebook;
	int i;
	
	gtk_init(&g_argc, &g_argv);

	// build interface

	window = gtk_dialog_new();

	vbox = GTK_DIALOG(window)->vbox;
	action_area = GTK_DIALOG(window)->action_area;

	// add notebook to window
	
	notebook = gtk_notebook_new();
	
	gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);

	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), 2);

	// add pages

	for(i=0; i<num_clusters; i++) {

		cluster_t *cluster = clusters[i];
		GtkWidget *label = gtk_label_new(cluster->name);
		GtkWidget *page = create_cluster_page(cluster);
		
		gtk_notebook_append_page
			(GTK_NOTEBOOK(notebook),
			 page,
			 label);
	}

	{
		statusbar = gtk_statusbar_new();

		gtk_box_pack_start(GTK_BOX(vbox), statusbar, 
				   FALSE,FALSE, 0);

		gtk_statusbar_push(GTK_STATUSBAR(statusbar),
				   1,
				   "Scanning...");

		gtk_widget_show(statusbar);
	}

	{
		GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
		GtkWidget *close_button 
			= gtk_button_new_with_label("Close");

		gtk_box_pack_start(GTK_BOX(action_area), hbox,
				   TRUE, TRUE, 0);

		gtk_signal_connect (GTK_OBJECT (close_button), 
				    "clicked",
				    GTK_SIGNAL_FUNC(gtk_main_quit),
				    NULL);


		gtk_box_pack_end(GTK_BOX(hbox), close_button,
				 FALSE, FALSE, 0);


#ifdef CSLIB
		{
			GtkWidget *logo = load_cslib_logo();
			gtk_box_pack_start(GTK_BOX(hbox), logo,
					   FALSE, FALSE, 0);
			gtk_widget_show(logo);
		}
#endif /* #ifdef CSLIB */
		
		gtk_widget_show(hbox);
		gtk_widget_show(close_button);
	}

	// close event
	gtk_signal_connect (GTK_OBJECT(window), "delete_event",
			    GTK_SIGNAL_FUNC (gtk_main_quit), NULL);

	// set a reasonable size

	gtk_window_set_default_size(GTK_WINDOW(window), 384, 256);

	// show notebook
	gtk_widget_show(notebook);

	// show window
	gtk_widget_show(window);
}

void ui_add_user(machine_t *machine, user_t *user)
{
	gtkdata_t *gtkdata = (gtkdata_t *) machine->interface_data;

	// if we dont have a subtree already, add one

	if(!gtkdata->subtree) {
		gtkdata->subtree = gtk_tree_new();
		gtk_tree_item_set_subtree(GTK_TREE_ITEM(gtkdata->treeitem), 
					  gtkdata->subtree);

		gtk_tree_item_expand(GTK_TREE_ITEM(gtkdata->treeitem));
	}

	// create new item and add to list

	{
		GtkWidget *item = gtk_tree_item_new();
                
                {
                        GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
                        GtkWidget *label = gtk_label_new(user->name);
                        GtkWidget *icon = 
                                gtk_pixmap_new(user_icon, user_icon_mask);

                        gtk_box_pack_start (GTK_BOX (hbox),
                                            icon, 
                                            FALSE, FALSE, 3);
                        
                        gtk_box_pack_start (GTK_BOX (hbox), 
                                            label,
                                            FALSE, FALSE, 3);

                        gtk_widget_show(icon);
                        gtk_widget_show(label);
                        gtk_widget_show(hbox);

                        gtk_container_add (GTK_CONTAINER(item), hbox);
                }

		gtk_tree_append(GTK_TREE(gtkdata->subtree), item);

		gtk_widget_show(item);
	}
}

void ui_set_status(machine_t *machine, machinestatus_t status)
{
        if(status == STATUS_DOWN || status == STATUS_FAULT) {
                GtkRcStyle *rcs = gtk_rc_style_new();
                GdkColor col;
        
                gdk_color_parse(status == STATUS_DOWN ? "red" : "blue", &col);
        
                rcs->fg[GTK_STATE_NORMAL] = col;
                rcs->color_flags[GTK_STATE_NORMAL] |= GTK_RC_FG;
                gtk_widget_modify_style(((gtkdata_t *) machine->interface_data)->textlabel, rcs);

                gtk_rc_style_unref(rcs);
                
        }

	gtk_widget_show(((gtkdata_t *) machine->interface_data)->label);
}

static int scan_callback_ref;

static gint scan_callback_func(gpointer data)
{
	scan_update();

	if(!scan_waiting()) {
		gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 1);

		gtk_statusbar_push(GTK_STATUSBAR(statusbar),
				   1,
				   "Scan Complete.");

		gtk_idle_remove(scan_callback_ref);
	}
	
	return 1;
}

void ui_run()
{
	scan_callback_ref = gtk_idle_add(scan_callback_func, NULL);

	gtk_main();
}

void *ui_new_interface_data(machine_t *machine)
{
	return (void *) malloc(sizeof(gtkdata_t));
}
