
#include <stdlib.h>
#include <glib.h>
#include <gmodule.h>
#include <gtk/gtkmain.h>
#include <gtk/gtksignal.h>
#include <multisync.h>
#include "support.h"
#include "gui.h"
#include "interface.h"
#include "syncml_cmd.h"
#include "syncml_plugin.h"


GtkWidget* syncmlwindow = NULL, *syncmlmessage = NULL;
syncml_connection *syncmlconn = NULL;
syncml_conn_type syncmlproto = SYNCML_CONN_TYPE_UNKNOWN;


void syncml_server_selected(GtkMenuItem *menuitem) {
  gtk_entry_set_editable(GTK_ENTRY(lookup_widget(syncmlwindow,
						 "hostnameentry")), FALSE);  
  gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(syncmlwindow,
						    "hostnameentry")), FALSE);
  gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(syncmlwindow,
						    "devinfobutton")), FALSE);

  gtk_entry_set_text(GTK_ENTRY(lookup_widget(syncmlwindow, "calendarentry")), 
		     "calendar");
  gtk_entry_set_editable(GTK_ENTRY(lookup_widget(syncmlwindow,
						 "calendarentry")), FALSE);  
  gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(syncmlwindow,
						    "calendarentry")), FALSE);
  gtk_entry_set_text(GTK_ENTRY(lookup_widget(syncmlwindow, "phonebookentry")), 
		     "addressbook");
  gtk_entry_set_editable(GTK_ENTRY(lookup_widget(syncmlwindow,
						 "phonebookentry")), FALSE);  
  gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(syncmlwindow,
						    "phonebookentry")), FALSE);

  gtk_entry_set_text(GTK_ENTRY(lookup_widget(syncmlwindow, "hostnameentry")), 
		     "<this computer>");
  syncmlconn->isserver = TRUE;
}

void syncml_client_selected(GtkMenuItem *menuitem) {
  gtk_entry_set_editable(GTK_ENTRY(lookup_widget(syncmlwindow,
						 "hostnameentry")), TRUE);
  gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(syncmlwindow,
						    "hostnameentry")), TRUE);
  gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(syncmlwindow,
						    "devinfobutton")), TRUE);

  gtk_entry_set_editable(GTK_ENTRY(lookup_widget(syncmlwindow,
						 "calendarentry")), TRUE);  
  gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(syncmlwindow,
						    "calendarentry")), TRUE);
  gtk_entry_set_editable(GTK_ENTRY(lookup_widget(syncmlwindow,
						 "phonebookentry")), TRUE);  
  gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(syncmlwindow,
						    "phonebookentry")), TRUE);

  syncmlconn->isserver = FALSE;
}

void syncml_conn_type_selected(GtkMenuItem *menuitem, syncml_conn_type type) {
  syncmlproto = type;
}

GtkWidget* open_option_window(sync_pair *pair, connection_type type) {
  if (!syncmlwindow) {  
    GtkWidget *menu;
    GtkWidget *menuitem;
    char *str;
    gboolean allzerokey = TRUE;
    int t;

    // The current active connection, if exists
    syncmlconn = g_malloc0(sizeof(syncml_connection));
    syncmlconn->sync_pair = pair;
    syncmlconn->conntype = type;
    syncml_load_state(syncmlconn);
    if (!syncmlconn->serverURI)
      syncmlconn->serverURI = g_strdup("https://<this computer>:5079/");
    syncmlproto = syncml_get_URI_proto(syncmlconn->serverURI);
    if (syncmlproto == SYNCML_CONN_TYPE_UNKNOWN)
      syncmlproto = SYNCML_CONN_TYPE_HTTPS; // Default https connection
    syncmlwindow = create_syncml_optwin();

    str = syncml_get_URI_host(syncmlconn->serverURI);
    if (str) {
      gtk_entry_set_text(GTK_ENTRY(lookup_widget(syncmlwindow, "hostnameentry")),
			 str);
      g_free(str);
    }
    str = syncml_get_URI_file(syncmlconn->serverURI);
    if (str) {
      if (str[0] == '/')
	gtk_entry_set_text(GTK_ENTRY(lookup_widget(syncmlwindow, 
						   "pathentry")), 
			   str+1);
      else
	gtk_entry_set_text(GTK_ENTRY(lookup_widget(syncmlwindow, 
						   "pathentry")), 
			   str);
    }
    g_free(str);
    str = g_strdup_printf("%d", syncml_get_URI_port(syncmlconn->serverURI));
    gtk_entry_set_text(GTK_ENTRY(lookup_widget(syncmlwindow, "portentry")),
		       str);
    g_free(str);
    if (syncmlconn->login)
      gtk_entry_set_text(GTK_ENTRY(lookup_widget(syncmlwindow, "loginentry")), 
			 syncmlconn->login);
    if (syncmlconn->passwd)
      gtk_entry_set_text(GTK_ENTRY(lookup_widget(syncmlwindow, "passwdentry")), 
			 syncmlconn->passwd);
    if (syncmlconn->othercalendardb)
      gtk_entry_set_text(GTK_ENTRY(lookup_widget(syncmlwindow, "calendarentry")), 
			 syncmlconn->othercalendardb);
    if (syncmlconn->otherphonebookdb)
      gtk_entry_set_text(GTK_ENTRY(lookup_widget(syncmlwindow, "phonebookentry")), 
			 syncmlconn->otherphonebookdb);
    

    menu = gtk_menu_new ();
    menuitem = gtk_menu_item_new_with_label (_("SyncML Server: Accept connections"));
    gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
			GTK_SIGNAL_FUNC (syncml_server_selected),
			NULL);
    gtk_menu_append (GTK_MENU (menu), menuitem);
    if (syncmlconn->isserver) {
      gtk_menu_item_activate(GTK_MENU_ITEM(menuitem));
      gtk_menu_set_active (GTK_MENU(menu), 0);
    }
    menuitem = gtk_menu_item_new_with_label (_("SyncML Client: Connect to a SyncML server"));
    gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
			GTK_SIGNAL_FUNC (syncml_client_selected),
			NULL);
    gtk_menu_append (GTK_MENU (menu), menuitem);
    if (!syncmlconn->isserver) {
      gtk_menu_item_activate(GTK_MENU_ITEM(menuitem));
      gtk_menu_set_active (GTK_MENU(menu), 1);
    }
    gtk_widget_show_all(GTK_WIDGET(menu));
    gtk_option_menu_set_menu (GTK_OPTION_MENU(lookup_widget(syncmlwindow,
							    "rolemenu")), 
			      menu);

    menu = gtk_menu_new ();
    menuitem = gtk_menu_item_new_with_label (_("http"));
    gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
			GTK_SIGNAL_FUNC (syncml_conn_type_selected),
			(gpointer) SYNCML_CONN_TYPE_HTTP);
    gtk_menu_append (GTK_MENU (menu), menuitem);
    if (syncmlproto == SYNCML_CONN_TYPE_HTTP) {
      gtk_menu_item_activate(GTK_MENU_ITEM(menuitem));
      gtk_menu_set_active (GTK_MENU(menu), 0);
    }
    menuitem = gtk_menu_item_new_with_label (_("https"));
    gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
			GTK_SIGNAL_FUNC (syncml_conn_type_selected),
			(gpointer) SYNCML_CONN_TYPE_HTTPS);
    gtk_menu_append (GTK_MENU (menu), menuitem);
    if (syncmlproto == SYNCML_CONN_TYPE_HTTPS) {
      gtk_menu_item_activate(GTK_MENU_ITEM(menuitem));
      gtk_menu_set_active (GTK_MENU(menu), 1);
    }
    gtk_widget_show_all(GTK_WIDGET(menu));
    gtk_option_menu_set_menu (GTK_OPTION_MENU(lookup_widget(syncmlwindow,
							    "protomenu")), 
			      menu);

    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(syncmlwindow,
								 "removeutccheck")), syncmlconn->removeutc);

    gtk_widget_show (syncmlwindow);
  }
  return(syncmlwindow);
}

void syncml_window_closed(void) {
  sync_plugin_window_closed();
  syncml_free_connection(syncmlconn);
  syncmlwindow = NULL;
  syncmlconn = NULL;
}

void syncml_cancel(void) {
  gtk_widget_destroy(syncmlwindow);
  syncml_window_closed();
}

gboolean syncml_get_window_data(void) {
  char *str;
  char *hostname, *portname, *pathname, *protoname="none";
  char *login, *passwd;
  int portno = 0;
  hostname = (char*) gtk_entry_get_text(GTK_ENTRY(lookup_widget(syncmlwindow, "hostnameentry")));
  if (strlen(hostname) == 0 && syncmlconn->isserver)
    hostname = "<this computer>";
  if (strlen(hostname) == 0 && !syncmlconn->isserver) {
    syncml_show_msg("Please set the network name of the server,\n"
		    "e.g. \"myserver.mydomain.com\".");
    return(FALSE);
  }
  portname = (char*) gtk_entry_get_text(GTK_ENTRY(lookup_widget(syncmlwindow, "portentry")));
  if (strlen(portname) > 0)
    sscanf(portname, "%d", &portno);
  pathname = (char*) gtk_entry_get_text(GTK_ENTRY(lookup_widget(syncmlwindow, "pathentry")));
  login = (char*) gtk_entry_get_text(GTK_ENTRY(lookup_widget(syncmlwindow, "loginentry")));
  passwd = (char*) gtk_entry_get_text(GTK_ENTRY(lookup_widget(syncmlwindow, "passwdentry")));
  if (strlen(passwd) == 0 || strlen(passwd) == 0) {
    if (syncmlconn->isserver)
      syncml_show_msg("Please set a login name and password for\n"
		      "the SyncML server. For security reasons,\n"
		      "do not use the same password you use to login\n"
		      "to this this computer.");
    else
      syncml_show_msg("Please set a login name and password for\n"
		      "the SyncML server.");
    return(FALSE);
  }
  if (syncmlconn->login)
    g_free(syncmlconn->login);
  if (syncmlconn->passwd)
    g_free(syncmlconn->passwd);
  syncmlconn->login = g_strdup(login);
  syncmlconn->passwd = g_strdup(passwd);
  if (syncmlconn->othercalendardb)
    g_free(syncmlconn->othercalendardb);
  if (syncmlconn->otherphonebookdb)
    g_free(syncmlconn->otherphonebookdb);
  syncmlconn->othercalendardb = g_strdup(gtk_entry_get_text(GTK_ENTRY(lookup_widget(syncmlwindow, "calendarentry"))));
  syncmlconn->otherphonebookdb = g_strdup(gtk_entry_get_text(GTK_ENTRY(lookup_widget(syncmlwindow, "phonebookentry"))));
  
  if (syncmlconn->serverURI)
    g_free(syncmlconn->serverURI);
  if (syncmlproto == SYNCML_CONN_TYPE_HTTP)
    protoname = "http";
  if (syncmlproto == SYNCML_CONN_TYPE_HTTPS)
    protoname = "https";
  if (portno > 0)
    syncmlconn->serverURI = 
      g_strdup_printf("%s://%s:%d/%s", protoname, hostname, portno, pathname);
  else
    syncmlconn->serverURI = 
      g_strdup_printf("%s://%s/%s", protoname, hostname, pathname);

  syncmlconn->removeutc = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(syncmlwindow,"removeutccheck")));

  return(TRUE);
}




void syncml_ok(void) {
  if (syncml_get_window_data()) {
    gtk_widget_destroy(syncmlwindow);
    if (syncmlconn) {
      syncml_save_state(syncmlconn);
    }
    syncml_window_closed();
  }
}


void syncml_show_msg(char *msg) {
  if (syncmlmessage) {
    gtk_widget_destroy(syncmlmessage);
    gtk_widget_unref(syncmlmessage);
    syncmlmessage = NULL;
  }
  syncmlmessage = gnome_message_box_new(msg,
					GNOME_MESSAGE_BOX_ERROR,
					GNOME_STOCK_BUTTON_OK, NULL);
  gtk_window_set_title (GTK_WINDOW (syncmlmessage), "Syncml plugin");
  gtk_window_set_modal(GTK_WINDOW(syncmlmessage), TRUE);
  gtk_widget_ref(syncmlmessage);
  gtk_widget_show(syncmlmessage);
}

gboolean syncml_do_show_msg(gpointer msg) {
  syncml_show_msg((char*) msg);
  g_free(msg);
  return(FALSE);
}

void syncml_async_msg(char *msg) {
  g_idle_add(syncml_do_show_msg, g_strdup(msg));
}

gboolean syncml_show_question(char *msg) {
  gboolean ok = FALSE;
  if (syncmlmessage) {
    gtk_widget_destroy(syncmlmessage);
    gtk_widget_unref(syncmlmessage);
    syncmlmessage = NULL;
  }
  syncmlmessage = gnome_message_box_new(msg,
					 GNOME_MESSAGE_BOX_QUESTION,
					 GNOME_STOCK_BUTTON_OK,
					 GNOME_STOCK_BUTTON_CANCEL, NULL);
  gtk_window_set_title (GTK_WINDOW (syncmlmessage), "SyncML plugin");
  gtk_window_set_modal(GTK_WINDOW(syncmlmessage), TRUE);
  gtk_widget_show(syncmlmessage);
  ok = (gnome_dialog_run(GNOME_DIALOG(syncmlmessage))==0);
  return(ok);
}

void syncml_gui_get_devinfo(void) {
  // Fetch devinfo to be able to choose database
  if (syncml_get_window_data()) {
    if (syncml_start_syncml_engine(syncmlconn)) {
      char *msg = "Fetching device information from server...";
      syncmlmessage = gnome_message_box_new(msg,
					    GNOME_MESSAGE_BOX_INFO, NULL);
      gtk_window_set_title (GTK_WINDOW (syncmlmessage), "SyncML plugin");
      gtk_window_set_modal(GTK_WINDOW(syncmlmessage), TRUE);
      gtk_widget_ref(syncmlmessage);
      gtk_widget_show(syncmlmessage);
      syncml_get_devinfo(syncmlconn);
    }
  }
}

typedef struct {
  syncml_devinfo *devinfo;
  char *error;
} gui_devinfo_received_arg;

gboolean syncml_do_gui_devinfo_received(gpointer data) {
  gui_devinfo_received_arg *arg = data;
  syncml_devinfo *devinfo = arg->devinfo;
  char *error = arg->error;
  g_free(arg);
  if (syncmlconn->state)
    syncml_stop_syncml_engine(syncmlconn);
  if (syncmlmessage) {
    gtk_widget_destroy(syncmlmessage);
    gtk_widget_unref(syncmlmessage);
    syncmlmessage = NULL;
  }
  if (devinfo) {
    GList *paths = NULL;
    GList *stores = devinfo->datastores;
    while(stores) {
      gboolean found = FALSE;
      syncml_datastore *store = stores->data;
      GList *rx = store->rx;
      if (store->rxpref == SYNCML_DATA_TYPE_VCALENDAR1 ||
	  store->rxpref == SYNCML_DATA_TYPE_VCALENDAR2)
	found = TRUE;
      while (rx) {
	syncml_data_type type = (syncml_data_type) rx->data;
	if (type == SYNCML_DATA_TYPE_VCALENDAR1 ||
	    type == SYNCML_DATA_TYPE_VCALENDAR2)
	  found = TRUE;
	rx = rx->next;
      }
      if (found) {
	paths = g_list_append(paths, store->sourceref);
      }
      stores = stores->next;
    }
    gtk_combo_set_popdown_strings(GTK_COMBO(lookup_widget(syncmlwindow,
							  "calendarcombo")),
				  paths);
    g_list_free(paths);
    paths = NULL;

    // Again, now for phonebook
    stores = devinfo->datastores;
    while(stores) {
      gboolean found = FALSE;
      syncml_datastore *store = stores->data;
      GList *rx = store->rx;
      if (store->rxpref == SYNCML_DATA_TYPE_VCARD21 ||
	  store->rxpref == SYNCML_DATA_TYPE_VCARD30)
	found = TRUE;
      while (rx) {
	syncml_data_type type = (syncml_data_type) rx->data;
	if (type == SYNCML_DATA_TYPE_VCARD21 ||
	    type == SYNCML_DATA_TYPE_VCARD30)
	  found = TRUE;
	rx = rx->next;
      }
      if (found) {
	paths = g_list_append(paths, store->sourceref);
      }
      stores = stores->next;
    }
    gtk_combo_set_popdown_strings(GTK_COMBO(lookup_widget(syncmlwindow,
							  "phonebookcombo")),
				  paths);
    g_list_free(paths);
    paths = NULL;
  }
  if (error) {
    syncml_show_msg(error);
    g_free(error);
  }
  return(FALSE);
}

void syncml_gui_devinfo_received(syncml_devinfo *devinfo, char* error) {
  gui_devinfo_received_arg *arg = g_malloc0(sizeof(gui_devinfo_received_arg));
  arg->devinfo = devinfo;
  arg->error = g_strdup(error);
  g_idle_add(syncml_do_gui_devinfo_received, arg);
}
