/*
Copyright (C) 2003 by Sean David Fleming

sean@ivec.org

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.

The GNU GPL can also be found at http://www.gnu.org
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "gdis.h"
#include "host.h"
#include "job.h"
#include "task.h"
#include "file.h"
#include "parse.h"
#include "dialog.h"
#include "interface.h"
#include "gui_shorts.h"
#include "grid.h"
#include "grisu_client.h"

extern struct sysenv_pak sysenv;

GtkListStore *grisu_ls=NULL;
GtkWidget *grisu_tv=NULL;
GtkListStore *grid_ls=NULL;
GtkWidget *grid_tv=NULL;
GtkListStore *job_ls=NULL;
GtkWidget *job_tv=NULL;
GtkWidget *grid_id_label, *grid_id_entry, *grid_password_entry, *grid_status_entry;
GtkWidget *grid_vo_combo;
GtkWidget *grid_configure_box;
GtkWidget *grid_service_entry;
GtkWidget *grid_myproxy_server_entry;
GtkWidget *grid_myproxy_port_entry;
GSList *grid_vo_list=NULL;
GtkListStore *grid_vo_store=NULL;
gint grid_method = GRID_MYPROXY;

/* CURRENT - used to enforce 1 background gui task at a time */
GMutex *gui_grid_mutex=NULL;
GtkWidget *grid_status_bar;


/* CURRENT - data struct for background tasks */

struct grid_data_pak
{
gchar *application;
GSList *queues;
GSList *jobname;
GSList *status;
GSList *files;
};

gpointer grid_data_new(void)
{
struct grid_data_pak *data;

data = g_malloc(sizeof(struct grid_data_pak));

data->application=NULL;
data->queues=NULL;
data->jobname = NULL;
data->status = NULL;
data->files = NULL;

return(data);
}

void grid_data_free(struct grid_data_pak *data)
{
g_assert(data != NULL);

g_free(data->application);

free_slist(data->queues);
free_slist(data->jobname);
free_slist(data->status);
free_slist(data->files);

g_free(data);
}

/***************************************************/
/* primtives for activity with unknown work length */
/***************************************************/
gint grid_task_start(void)
{
if (g_mutex_trylock(gui_grid_mutex))
  {
  if (GTK_IS_ENTRY(grid_status_bar))
    gtk_entry_set_text(GTK_ENTRY(grid_status_bar), "Operation in progress, please wait ...");
  return(TRUE);
  }
else
  printf("I'm busy, please wait.\n");

return(FALSE);
}

void grid_task_stop(void)
{
if (GTK_IS_ENTRY(grid_status_bar))
  gtk_entry_set_text(GTK_ENTRY(grid_status_bar), "");
g_mutex_unlock(gui_grid_mutex);
}

void grid_task_feedback(const gchar *text)
{
if (GTK_IS_ENTRY(grid_status_bar))
  gtk_entry_set_text(GTK_ENTRY(grid_status_bar), text);
}

/*********************************/
/* GUI vo entry changed callback */
/*********************************/
void gui_vo_changed(GtkWidget *w, gpointer data)
{
#ifdef WITH_GRISU
const gchar *vo;

vo = gtk_entry_get_text(GTK_ENTRY(GTK_BIN(grid_vo_combo)->child));

if (g_strncasecmp(vo, "no", 2) == 0)
  grisu_vo_set("");
else
  grisu_vo_set(vo);
#endif
}

/*****************************/
/* refresh VO combo pulldown */
/*****************************/
void gui_vo_refresh(void)
{
#if GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 4
GSList *list;
GtkTreeIter iter;

g_assert(grid_vo_store != NULL);

gtk_list_store_clear(grid_vo_store);

for (list=grid_vo_list ; list ; list=g_slist_next(list))
  {
  gtk_list_store_append(grid_vo_store, &iter);
  gtk_list_store_set(grid_vo_store, &iter, 0, list->data, -1);
  }

/* TODO - print this text as the default on startup */
gtk_list_store_prepend(grid_vo_store, &iter);
gtk_list_store_set(grid_vo_store, &iter, 0, "No VO", -1);

#else
/* use deprec combo */
#endif
}

/*************************************/
/* change grid authentication method */
/*************************************/
void gui_grid_method(GtkWidget *w, gpointer dummy)
{
#ifdef WITH_GRISU
gchar *subject;
const gchar *text;

if (w)
  {
/* change event only */
  text = gtk_label_get_text(GTK_LABEL(grid_id_label));
  if (g_strncasecmp(text, "grid", 4) == 0)
    grid_method = GRID_MYPROXY;
  else
    grid_method = GRID_LOCALPROXY;
  }
else
  {
/* initial setup */
  switch (grid_method)
    {
    case GRID_MYPROXY:
/* want the user to enter this, so scrub the default */
      grisu_keypair_set("","");
      break;

    case GRID_LOCALPROXY:
/* auto generate these */
      grisu_keypair_set(grid_random_alpha(10),grid_random_alphanum(12));
      break;
    }
  }

/* common GUI update */
switch (grid_method)
  {
  case GRID_MYPROXY:
    gtk_label_set_text(GTK_LABEL(grid_id_label), "Username");
    text = grisu_username_get();
    if (text)
      gtk_entry_set_text(GTK_ENTRY(grid_id_entry), text);
    else
      gtk_entry_set_text(GTK_ENTRY(grid_id_entry), "");
    break;

  case GRID_LOCALPROXY:
    gtk_label_set_text(GTK_LABEL(grid_id_label), "Grid Identity");
    subject = grid_get_DN("/home/sean/.globus/usercert.pem");
    gtk_entry_set_text(GTK_ENTRY(grid_id_entry), subject);
    g_free(subject);
    break;
  }
#endif
}

/*************************************************/
/* toggle the display of the configuration panel */
/*************************************************/
void gui_grid_configure(gpointer dummy)
{
static gint visible=TRUE;

if (visible)
  {
  gtk_widget_hide(grid_configure_box);
  visible = FALSE;
  }
else
  {
  gtk_widget_show(grid_configure_box);
  visible = TRUE;

#ifdef WITH_GRISU
/* update boxes with data */
  gtk_entry_set_text(GTK_ENTRY(grid_service_entry), grisu_ws_get());
  gtk_entry_set_text(GTK_ENTRY(grid_myproxy_server_entry), grisu_myproxy_get());
  gtk_entry_set_text(GTK_ENTRY(grid_myproxy_port_entry), grisu_myproxyport_get());
#endif
  }
}

/********************************/
/* grid connect background task */
/********************************/
void grid_connect_start(gpointer dummy)
{
#ifdef WITH_GRISU
grid_vo_list = grisu_fqans_get();

/* FIXME - is a NULL vo list proof of failed auth? */
if (grid_vo_list)
  grid_auth_set(TRUE);
else
  grid_auth_set(FALSE);
#endif
}

/********************************/
/* grid connect GUI update task */
/********************************/
void grid_connect_stop(gpointer dummy)
{
gui_vo_refresh();

gtk_entry_set_text(GTK_ENTRY(grid_status_entry), grid_get_status());

grid_task_stop();
}

/***************************************/
/* apply current authentication method */
/***************************************/
void gui_grid_connect(GtkWidget *w, gpointer dummy)
{
#ifdef WITH_GRISU
/* CURRENT - mutex lock - 1 grid op at a time */
if (!grid_task_start())
  return;

switch (grid_method)
  {
  case GRID_MYPROXY:
    grisu_keypair_set(gtk_entry_get_text(GTK_ENTRY(grid_id_entry)),
                      gtk_entry_get_text(GTK_ENTRY(grid_password_entry)));
    break; 

  case GRID_LOCALPROXY:
    grisu_keypair_set(NULL, gtk_entry_get_text(GTK_ENTRY(grid_password_entry)));
/* upload proxy */
    grid_connect(grid_method);
    break;
  }

/* get VO's for display (also serves as auth check) */
grisu_auth_set(TRUE);

if (grid_vo_list)
  free_slist(grid_vo_list);

task_new("Authenticate", grid_connect_start, NULL, grid_connect_stop, NULL, NULL);
#endif
}

/**********************/
/* grid configuration */
/**********************/
void gui_grid_setup_page(GtkWidget *box, gpointer dialog)
{
GtkWidget *table, *label, *button;

table = gtk_table_new(3, 4, FALSE);
gtk_box_pack_start(GTK_BOX(box), table, FALSE, FALSE, 0);

/* reflect the authentication mechanism (grid proxy, myproxy, shib?) */
grid_id_label = gtk_label_new(" xxxxxxxxxxxxxxxx ");
gtk_table_attach(GTK_TABLE(table),grid_id_label,0,1,0,1, GTK_SHRINK, GTK_SHRINK, 0, 0);

label = gtk_label_new(" Password ");
gtk_table_attach(GTK_TABLE(table),label,0,1,1,2, GTK_SHRINK, GTK_SHRINK, 0, 0);

label = gtk_label_new(" Status ");
gtk_table_attach(GTK_TABLE(table),label,0,1,2,3, GTK_SHRINK, GTK_SHRINK, 0, 0);

grid_id_entry = gtk_entry_new();
gtk_table_attach_defaults(GTK_TABLE(table),grid_id_entry,1,2,0,1);

grid_password_entry = gtk_entry_new();
gtk_entry_set_visibility(GTK_ENTRY(grid_password_entry), FALSE);
gtk_table_attach_defaults(GTK_TABLE(table),grid_password_entry,1,2,1,2);
g_signal_connect(GTK_OBJECT(grid_password_entry), "activate",
                 GTK_SIGNAL_FUNC(gui_grid_connect), NULL);

grid_status_entry = gtk_entry_new();
gtk_table_attach_defaults(GTK_TABLE(table),grid_status_entry,1,2,2,3);
gtk_entry_set_text(GTK_ENTRY(grid_status_entry), grid_get_status());

//button = gui_button("Authenticate", gpointer cb, gpointer arg, NULL, 0);

/* TODO - this is inteded for specifying certificate location (assuming not in default location) */
/* TODO - also for specifying what myproxy server / port / etc to use */
button = gui_button(" Configure ", gui_grid_configure, NULL, NULL, 0);
gtk_table_attach(GTK_TABLE(table),button,2,3,0,1, GTK_FILL, GTK_FILL, 0, 0);

/* this is for uploading a credential to the myproxy server */
button = gui_button(" Connect ", gui_grid_connect, NULL, NULL, 0);
gtk_table_attach(GTK_TABLE(table),button,2,3,1,2, GTK_FILL, GTK_FILL, 0, 0);

#if GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 4

/* create store and fill it */
grid_vo_store = gtk_list_store_new(1, G_TYPE_STRING);
gui_vo_refresh();

/* create combo box and set start value */
grid_vo_combo = gtk_combo_box_entry_new_with_model(GTK_TREE_MODEL(grid_vo_store), 0);
gtk_entry_set_text(GTK_ENTRY(GTK_BIN(grid_vo_combo)->child), "No VO");

gtk_table_attach(GTK_TABLE(table),grid_vo_combo,2,3,2,3, GTK_FILL, GTK_FILL, 0, 0);

g_signal_connect(GTK_OBJECT(GTK_BIN(grid_vo_combo)->child), "changed",
                 GTK_SIGNAL_FUNC(gui_vo_changed), NULL);

#else
// < GTK 2.2
// what to do here?
#endif

/* init for default method */
gui_grid_method(NULL, NULL);
}

/********************/
/* back ground task */
/********************/
void grid_refresh_all_start(gpointer data)
{
#ifdef WITH_GRISU
const gchar *status;
GSList *list;
struct grid_data_pak *grid_data = data;

g_assert(grid_data != NULL);

/* query grisu for all job names */
grid_data->jobname = grisu_job_names();
grid_data->status = NULL;

for (list=grid_data->jobname ; list ; list=g_slist_next(list))
  {
  status = grisu_job_status(list->data);
  grid_data->status = g_slist_prepend(grid_data->status, g_strdup(status));
  }

grid_data->status = g_slist_reverse(grid_data->status);
#endif
}

/*******************/
/* GUI update task */
/*******************/
void grid_refresh_all_stop(gpointer data)
{
#ifdef WITH_GRISU
const gchar *name, *status;
GSList *list1, *list2;
GtkTreeIter iter;
struct grid_data_pak *grid_data = data;

g_assert(grid_data != NULL);

gtk_list_store_clear(job_ls);

list2 = grid_data->status;
for (list1=grid_data->jobname ; list1 ; list1=g_slist_next(list1))
  {
  name = list1->data;
  if (list2)
    status = list2->data;
  else
    status = "undefined";  // shouldn't happen

  gtk_list_store_append(job_ls, &iter);
  gtk_list_store_set(job_ls, &iter, 0, name, 1, status, -1);

  list2 = g_slist_next(list2);
  }

grid_data_free(grid_data);

grid_task_stop();
#endif
}

/**********************/
/* refresh everything */
/**********************/
void gui_job_refresh_all(void)
{
#ifdef WITH_GRISU
struct grid_data_pak *data;

if (g_strncasecmp(grid_get_status(), "not", 3) == 0)
  {
  grid_task_feedback("Not authenticated.");
  return;
  }

/* CURRENT - mutex lock - 1 grid op at a time */
if (!grid_task_start())
  return;

data = grid_data_new();

task_new("Job list", grid_refresh_all_start, data, grid_refresh_all_stop, data, NULL);
#endif
}

/**************************************/
/* Refresh the status of selected job */
/**************************************/
void gui_job_refresh_selected(void)
{
#ifdef WITH_GRISU
const gchar *name, *status;
GList *list, *row;
GtkTreeModel *treemodel;
GtkTreeSelection *selection;
GtkTreeIter iter;

/* CURRENT - mutex lock - 1 grid op at a time */
if (!grid_task_start())
  return;

treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(job_tv));
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(job_tv));

list = gtk_tree_selection_get_selected_rows(selection, &treemodel);

for (row=list ; row ; row=g_list_next(row))
  {
  if (gtk_tree_model_get_iter(treemodel, &iter, row->data))
    {
    gtk_tree_model_get(treemodel, &iter, 0, &name, -1);

/* TODO - get job details? eg vo etc */
    status = grisu_job_status(name);
    if (status)
      gtk_list_store_set(job_ls, &iter, 1, status, -1);
    }
  }
grid_task_stop();
#endif
}

/****************************/
/* Download background task */
/****************************/
void grid_job_download_start(gpointer data)
{
GSList *list;
struct grid_data_pak *grid_data = data;

g_assert(grid_data != NULL);
g_assert(grid_data->jobname != NULL);

list = grid_data->jobname; 

grid_data->files = grid_download_job(list->data);
}

/*******************/
/* GUI update task */
/*******************/
void grid_job_download_stop(gpointer data)
{
GSList *list;
struct grid_data_pak *grid_data = data;

g_assert(grid_data != NULL);
g_assert(grid_data->jobname != NULL);

list = grid_data->jobname;

grid_process_job(list->data, grid_data->files);

grid_data_free(grid_data);
}

/*****************************************************/
/* Retrieve output from a selected job (if complete) */
/*****************************************************/
void gui_job_download(GtkWidget *w, gpointer dummy)
{
const gchar *name, *status;
GList *list, *row;
GtkTreeModel *treemodel;
GtkTreeSelection *selection;
GtkTreeIter iter;
struct grid_data_pak *data;

/* FIXME - need to make grisu_client (especially soap stuff) thread safe */
if (!grid_task_start())
  return;

/* get selected job names for downloading */
treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(job_tv));
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(job_tv));

list = gtk_tree_selection_get_selected_rows(selection, &treemodel);

for (row=list ; row ; row=g_list_next(row))
  {
  if (gtk_tree_model_get_iter(treemodel, &iter, row->data))
    {
    gtk_tree_model_get(treemodel, &iter, 0, &name, 1, &status, -1);
    if (g_strncasecmp(status, "done", 4) == 0)
      {
/* FIXME - won't behave correctly for multiple downloads */
/* CURRENT - mutex lock - 1 grid op at a time */
      data = grid_data_new();
      data->jobname = g_slist_prepend(data->jobname, g_strdup(name));

      task_new("Download", grid_job_download_start, data, grid_job_download_stop, data, NULL);
      }
    }
  }

/* release the mutex lock because downloads are allowed to be queued as long */
/* as they are not done simulataneously (until soap stuff is thread safe) */
grid_task_stop();
}

/******************************/
/* background job remove task */
/******************************/
void grid_job_remove_start(gpointer data)
{
#ifdef WITH_GRISU
GSList *list;
struct grid_data_pak *grid_data = data;

g_assert(grid_data != NULL);

for (list=grid_data->jobname ; list ; list=g_slist_next(list))
  grisu_job_remove(list->data);
#endif
}

/******************/
/* completed task */
/******************/
void grid_job_remove_stop(gpointer data)
{
#ifdef WITH_GRISU
struct grid_data_pak *grid_data = data;

g_assert(grid_data != NULL);

grid_data_free(grid_data);
grid_task_stop();
#endif
}

/*************************************/
/* stop and cleanup the selected job */
/*************************************/
void gui_job_remove(GtkWidget *w, gpointer dummy)
{
#ifdef WITH_GRISU
const gchar *name;
GList *list, *row;
GtkTreeModel *treemodel;
GtkTreeSelection *selection;
GtkTreeIter iter;
struct grid_data_pak *grid_data;

/* CURRENT - mutex lock - 1 grid op at a time */
if (!grid_task_start())
  return;

grid_data = grid_data_new();

treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(job_tv));
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(job_tv));

/* NB: remove in reverse order so we dont get the iterators confused */
list = gtk_tree_selection_get_selected_rows(selection, &treemodel);
list = g_list_reverse(list);

for (row=list ; row ; row=g_list_next(row))
  {
  if (gtk_tree_model_get_iter(treemodel, &iter, row->data))
    {
    gtk_tree_model_get(treemodel, &iter, 0, &name, -1);
//    grisu_job_remove(name);
    grid_data->jobname = g_slist_prepend(grid_data->jobname, g_strdup(name));

    gtk_list_store_remove(job_ls, &iter);
    }
  }

task_new("Job remove", grid_job_remove_start, grid_data, grid_job_remove_stop, grid_data, NULL);
#endif
}

/***********************/
/* job monitoring page */
/***********************/
void gui_grid_monitoring_page(GtkWidget *box, gpointer dialog)
{
gchar *titles[] = {" Name ", " Status " };
GtkWidget *swin, *hbox, *vbox;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkTreeSelection *selection;

g_assert(box != NULL);

vbox = gui_frame_vbox(NULL, TRUE, TRUE, box);

swin = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
                               GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start(GTK_BOX(vbox), swin, TRUE, TRUE, 0);

job_ls = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
job_tv = gtk_tree_view_new_with_model(GTK_TREE_MODEL(job_ls));
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), job_tv);

renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(titles[0], renderer, "text", 0, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(job_tv), column);
gtk_tree_view_column_set_expand(column, FALSE);

renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(titles[1], renderer, "text", 1, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(job_tv), column);
gtk_tree_view_column_set_expand(column, TRUE);

selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(job_tv));
gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);

hbox = gtk_hbox_new(TRUE, PANEL_SPACING);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);

/* TODO ... then automate */
gui_button(" Refresh all", gui_job_refresh_all, NULL, hbox, 0);
/* TODO - refresh selected */
gui_button(" Refresh ", gui_job_refresh_selected, NULL, hbox, 0);
/* upload is part of submit job */
//gui_button(" Upload ", gui_job_upload, NULL, hbox, 0);
gui_button(" Download ", gui_job_download, NULL, hbox, 0);
//gui_button(" Stop ", NULL, NULL, hbox, 0);
gui_button(" Remove ", gui_job_remove, NULL, hbox, 0);

}

/******************************************/
/* background task for application search */
/******************************************/
void grid_find_start(gpointer data)
{
struct grid_data_pak *grid_data = data;

g_assert(grid_data != NULL);

grid_data->queues = grid_search_by_name(grid_data->application);
}

/*******************/
/* GUI update task */
/*******************/
void grid_find_stop(gpointer data)
{
GSList *list;
GtkTreeIter iter;
struct grid_data_pak *grid_data = data;

g_assert(grid_data != NULL);

gtk_list_store_clear(grisu_ls);

for (list=grid_data->queues ; list ; list=g_slist_next(list))
  {
  gtk_list_store_append(grisu_ls, &iter);
  gtk_list_store_set(grisu_ls, &iter, 0, grid_data->application, 1, list->data, -1);
  }

grid_data_free(grid_data);

grid_task_stop();
}

/****************************/
/* connect to host callback */
/****************************/
void gui_grid_find(GtkWidget *w, gpointer dialog)
{
GtkEntry *entry;
struct grid_data_pak *grid_data;

/* CURRENT - mutex lock - 1 grid op at a time */
if (!grid_task_start())
  return;

entry = dialog_child_get(dialog, "application");

grid_data = grid_data_new();
grid_data->application = g_strdup(gtk_entry_get_text(entry));

/* clear old list */
task_new("Discovery", grid_find_start, grid_data, grid_find_stop, grid_data, NULL);
}

/****************************/
/* populate registered list */
/****************************/
void gui_grid_register_refresh(void)
{
gchar *key, *value;
GList *item, *list;
GtkTreeIter iter;

list = grid_application_all();

/* clear old GUI list */
gtk_list_store_clear(grid_ls);

for (item=list ; item ; item=g_list_next(item))
  {
  key = item->data;
  value = grid_application_get(key);

  gtk_list_store_append(grid_ls, &iter);
  gtk_list_store_set(grid_ls, &iter, 0, key, 1, value, -1);
  }
}

/*********************************/
/* set a new submission location */
/*********************************/
void gui_grid_register(GtkWidget *w, gpointer dummy)
{
const gchar *text1, *text2;
GtkTreeModel *treemodel;
GtkTreeSelection *selection;
GtkTreeIter iter;

treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(grisu_tv));
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(grisu_tv));

if (gtk_tree_selection_get_selected(selection, &treemodel, &iter))
  {
/* get application and location from selected item */
  gtk_tree_model_get(treemodel, &iter, 0, &text1, 1, &text2, -1);

//printf("Registering [%s][%s]\n", text1, text2);
//printf("Site = %s\n", grisu_site_name(text2));

/* register in hash table */
  grid_application_set(text1, text2);

/* refresh registered GUI list */
  gui_grid_register_refresh();
  }
else
  printf("Please select an entry from the Discovery list!\n");
}

/***********************************/
/* remove a registered application */
/***********************************/
void gui_grid_remove(GtkWidget *w, gpointer dummy)
{
const gchar *key;
GtkTreeModel *treemodel;
GtkTreeSelection *selection;
GtkTreeIter iter;

treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(grid_tv));
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(grid_tv));

if (gtk_tree_selection_get_selected(selection, &treemodel, &iter))
  {
/* get application from selected item */
  gtk_tree_model_get(treemodel, &iter, 0, &key, -1);

//printf("Removing: %s\n", key);

  grid_application_remove(key);

  gui_grid_register_refresh();
  }
 else
  printf("Please select an entry from the Registered list!\n");
}

/*****************************************/
/* setup/submit a registered application */
/*****************************************/
void gui_grid_job(GtkWidget *w, gpointer dummy)
{
#ifdef WITH_GRISU
gint type;
const gchar *name;
GtkTreeModel *treemodel;
GtkTreeSelection *selection;
GtkTreeIter iter;

if (!sysenv.active_model)
  {
printf("No active model.\n");
  return;
  }

treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(grid_tv));
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(grid_tv));

if (gtk_tree_selection_get_selected(selection, &treemodel, &iter))
  {
/* get application name from selected item */
  gtk_tree_model_get(treemodel, &iter, 0, &name, -1);

  type = grisu_job_type(name);

  switch (type)
    {
    case JOB_GULP:
      gulp_dialog();
      break;

    case JOB_GAMESS:
      gamess_dialog();
      break;
    }
  }
else
  {
  printf("Nothing selected.\n");
  }
#endif
}

/************************/
/* host setup/info page */
/************************/
void gui_grid_discover_page(GtkWidget *box, gpointer dialog)
{
gchar *titles[] = {" Application ", " Submission location " };
GtkWidget *swin, *hbox2, *vbox, *entry, *button;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;

/* left pane */
vbox = gui_frame_vbox(NULL, TRUE, TRUE, box);

/* available applications/queues list */
swin = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
                               GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start(GTK_BOX(vbox), swin, TRUE, TRUE, 0);

grisu_ls = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
grisu_tv = gtk_tree_view_new_with_model(GTK_TREE_MODEL(grisu_ls));
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), grisu_tv);

renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(titles[0], renderer, "text", 0, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(grisu_tv), column);
gtk_tree_view_column_set_expand(column, FALSE);

renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(titles[1], renderer, "text", 1, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(grisu_tv), column);
gtk_tree_view_column_set_expand(column, TRUE);

/* discovery functionality */
hbox2 = gtk_hbox_new(FALSE, 0);
gtk_box_pack_end(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);

/* search pattern */
entry = gtk_entry_new();
dialog_child_set(dialog, "application", entry);
gtk_box_pack_start(GTK_BOX(hbox2), entry, TRUE, TRUE, 0);
/* hit enter to trigger search */
g_signal_connect(GTK_OBJECT(entry), "activate", GTK_SIGNAL_FUNC(gui_grid_find), dialog);

/* search action */
button = gtk_button_new_with_label(" Search ");
g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gui_grid_find), dialog);
gtk_box_pack_start(GTK_BOX(hbox2), button, FALSE, FALSE, 0);

/* register action */
button = gtk_button_new_with_label(" Register ");
gtk_box_pack_start(GTK_BOX(hbox2), button, FALSE, FALSE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gui_grid_register), NULL);
}

/*********************************/
/* job setup and submission page */
/*********************************/
void gui_grid_submit_page(GtkWidget *box, gpointer dialog)
{
gchar *titles[] = {" Application ", " Submission location " };
GtkWidget *hbox2, *vbox, *button;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;

vbox = gui_frame_vbox(NULL, TRUE, TRUE, box);

/* registered applications */
grid_ls = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
grid_tv = gtk_tree_view_new_with_model(GTK_TREE_MODEL(grid_ls));
gtk_box_pack_start(GTK_BOX(vbox), grid_tv, TRUE, TRUE, 0);

renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(titles[0], renderer, "text", 0, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(grid_tv), column);
gtk_tree_view_column_set_expand(column, TRUE);

renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(titles[1], renderer, "text", 1, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(grid_tv), column);
gtk_tree_view_column_set_expand(column, TRUE);

/* registered functionality */
hbox2 = gtk_hbox_new(TRUE, 0);
gtk_box_pack_end(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);

button = gtk_button_new_with_label(" Unregister ");
gtk_box_pack_start(GTK_BOX(hbox2), button, FALSE, FALSE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gui_grid_remove), NULL);

/* TODO - configure job button (or auto pop up on submit) */
/* CURRENT - submit a job that tests the selected object */
button = gtk_button_new_with_label(" Setup job ");
gtk_box_pack_start(GTK_BOX(hbox2), button, FALSE, FALSE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gui_grid_job), NULL);

/* init GUI */
gui_grid_register_refresh();
}

/***************************/
/* configuration callbacks */
/***************************/
void gui_grid_ws_change(GtkWidget *w, gpointer dummy)
{
#ifdef WITH_GRISU
const gchar *ws;
ws = gtk_entry_get_text(GTK_ENTRY(grid_service_entry));
grisu_ws_set(ws);
#endif
}

void gui_grid_server_change(GtkWidget *w, gpointer dummy)
{
#ifdef WITH_GRISU
const gchar *server;
server = gtk_entry_get_text(GTK_ENTRY(grid_myproxy_server_entry));
grisu_myproxy_set(server, NULL);
#endif
}

void gui_grid_port_change(GtkWidget *w, gpointer dummy)
{
#ifdef WITH_GRISU
const gchar *port;
port = gtk_entry_get_text(GTK_ENTRY(grid_myproxy_port_entry));
grisu_myproxy_set(NULL, port);
#endif
}

/***********************/
/* configuration panel */
/***********************/
void gui_grid_configure_page(GtkWidget *box)
{
GtkWidget *table, *label;

g_assert(box != NULL);

table = gtk_table_new(2, 3, FALSE);
gtk_container_add(GTK_CONTAINER(box), table);

label = gtk_label_new("Service interface");
gtk_table_attach(GTK_TABLE(table),label,0,1,0,1, GTK_SHRINK, GTK_SHRINK, 0, 0);

label = gtk_label_new("Myproxy server ");
gtk_table_attach(GTK_TABLE(table),label,0,1,1,2, GTK_SHRINK, GTK_SHRINK, 0, 0);

label = gtk_label_new("Mpyroxy port ");
gtk_table_attach(GTK_TABLE(table),label,0,1,2,3, GTK_SHRINK, GTK_SHRINK, 0, 0);

grid_service_entry = gtk_entry_new();
gtk_table_attach_defaults(GTK_TABLE(table),grid_service_entry,1,2,0,1);
g_signal_connect(GTK_OBJECT(grid_service_entry), "changed",
                 GTK_SIGNAL_FUNC(gui_grid_ws_change), NULL);

grid_myproxy_server_entry = gtk_entry_new();
gtk_table_attach_defaults(GTK_TABLE(table),grid_myproxy_server_entry,1,2,1,2);
g_signal_connect(GTK_OBJECT(grid_myproxy_server_entry), "changed",
                 GTK_SIGNAL_FUNC(gui_grid_server_change), NULL);

grid_myproxy_port_entry = gtk_entry_new();
gtk_table_attach_defaults(GTK_TABLE(table),grid_myproxy_port_entry,1,2,2,3);
g_signal_connect(GTK_OBJECT(grid_myproxy_port_entry), "changed",
                 GTK_SIGNAL_FUNC(gui_grid_port_change), NULL);
}

/********************************************/
/* close dialog (if nothing is in progress) */
/********************************************/
void gui_grid_close(GtkWidget *w, gpointer data)
{
/* check for background task mutex */
if (!grid_task_start())
 return;

/* destroy */
dialog_destroy(NULL, data);

/* clear mutex */
grid_task_stop();
}

/*****************************/
/* the gdis job setup dialog */
/*****************************/
void gui_grid_dialog(void)
{
gpointer dialog;
GtkWidget *window, *vbox, *notebook, *page, *label;

if (!gui_grid_mutex)
  gui_grid_mutex = g_mutex_new();

/* CURRENT */
grid_setup();

dialog = dialog_request(666, "Grid Manager", NULL, NULL, NULL);
if (!dialog)
  return;
window = dialog_window(dialog);

vbox = gtk_vbox_new(FALSE, PANEL_SPACING);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->vbox), vbox);

gtk_widget_set_size_request(window, -1, 440);

/* authentication display */
page = gui_frame_vbox("Authentication", FALSE, FALSE, vbox);
gui_grid_setup_page(page, dialog);

/* configuration display */
grid_configure_box = gtk_frame_new("Configuration");
gtk_box_pack_start(GTK_BOX(vbox), grid_configure_box, FALSE, FALSE, 0);
gui_grid_configure_page(grid_configure_box);

/* notebook functionality splitting */
notebook = gtk_notebook_new();
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);

/* discovery page */
page = gtk_vbox_new(FALSE, 0);
label = gtk_label_new(" Discovery ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
gui_grid_discover_page(page, dialog);

/* submission/job configuration page */
page = gtk_vbox_new(FALSE, 0);
label = gtk_label_new(" Submission ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
gui_grid_submit_page(page, dialog);

/* job monitoring page */
page = gtk_vbox_new(FALSE, 0);
label = gtk_label_new(" Monitoring ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
gui_grid_monitoring_page(page, dialog);

/* CURRENT - indicate action in progress */
/* TODO - not really intended for download progress (as there may be more than 1) */
/* but rather as user feedback during (slow) grid responses to even simple commands */
grid_status_bar = gtk_entry_new();
gtk_entry_set_editable(GTK_ENTRY(grid_status_bar), FALSE);
gtk_box_pack_end(GTK_BOX(vbox), grid_status_bar, FALSE, FALSE, 0);

/* TODO - disallow even X close button if in the middle of a grid operation */
gui_stock_button(GTK_STOCK_CLOSE, gui_grid_close, dialog, GTK_DIALOG(window)->action_area);

gtk_widget_show_all(window);

/* default to hiden */
gtk_widget_hide(grid_configure_box);
}
