
/* servers_cb.c	-server stuff that is done via graphical interface

    Author: Tano Fotang, 1997

    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.
    see the file COPYING for more information.

*/

#include <forms.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/time.h>
#include <errno.h>
#include "config.h"
#include "nicks.h"
#include "aux.h"
#include "sula.h"
#include "servers.h"
#include "chanwin.h"
#include "global.h"

#define NO_BUG
extern FD_serverlist *server_tool;
static int i;
static void print_tree(Server *p , int pos){
	if(p){
		print_tree(p->right, pos+10);
		printf("%*.10s %d\n",pos,
		  p->servname, p->bf);
		print_tree(p->left, pos+10);
	}
}
static void loadlist(Server *p){
	char buf[512];

	if(p){
		loadlist( p->left);
		sprintf(buf,"@f%s%s%02d. %-30s %-5hu %-20s %-12s %-30s (%s)", 
		 p->fd>-1? "@b":"",p->connecting<0?"@i":"", i++,
	        p->servname, p->port, p->nick?p->nick:"?",
		aNickList[p->iNick].label?aNickList[p->iNick].label:"?",
		p->email?p->email:"?", 
		p->ircname?p->ircname:"?");
	     fl_addto_browser(server_tool->browser, buf);
	     loadlist(p->right);
	}
	
}

static void remove_server(void){
	int browser_line=fl_get_browser(server_tool->browser);

	if(browser_line<1){
	     fl_set_object_label(server_tool->status, "Remove what?");
     	    return;
       }
 	else{
		const char *buf;
		char servname[512];
		u_short port;
	    	buf=fl_get_browser_line(server_tool->browser, browser_line);
		if(sscanf(buf,"%*s %s %hu", servname, &port)<2){
		   	char *txt=(char*)malloc(sizeof(char)*(strlen(buf)+16));
		     	sprintf(txt,"Invalid: %s",buf);
			fl_set_object_label(server_tool->status,txt);
			free(txt);
     	   		return;
		}
		if(!remove_server_from_tree(servname,port)) {
			fl_set_object_label(server_tool->status,
		  	   "Cant remove server. Close associated wins first"); 
	        }else{
			fl_delete_browser_line(server_tool->browser, browser_line);
			fl_set_object_label(server_tool->status,"Ready");
			print_tree(servTree,4);
	       }
	}
 }

static void add(void){
	FD_add *form=create_form_add();
	/*FD_serverlist *f=(FD_serverlist *)ob->u_vdata;*/
	#ifndef NO_BUG
	server_tool->dismiss->u_ldata=1;
	#endif
	fl_set_cursor(server_tool->serverlist->window, XC_watch);
	fl_deactivate_form(server_tool->serverlist);
	/*fl_set_choice_text(form->nicklist,"default");*/
	form->ircname->u_ldata=form->nick->u_ldata= \
		form->email->u_ldata=form->password->u_ldata= \
		form->servername->u_ldata=form->port->u_ldata=(long)XC_xterm;
	fl_set_object_prehandler(form->input_grp, set_cursor);
	fl_set_object_prehandler(form->nick, set_cursor);
	fl_set_object_prehandler(form->email, set_cursor);
	fl_set_object_prehandler(form->servername, set_cursor);
	fl_set_object_prehandler(form->port, set_cursor);
	fl_set_object_prehandler(form->ircname, set_cursor);
	fl_set_object_prehandler(form->password, set_cursor);
	if(iNickListCount>0){
		int n=0;
	 	while(n<iNickListCount){
	 		if(aNickList[n].label)
			 	fl_addto_choice(form->nicklist,aNickList[n].label);
			n++;
	  	}
	}
	form->done->u_ldata=(long)0;	/*add*/
	fl_set_form_atclose(form->add, dont_close_win, 0);
	fl_show_form(form->add,FL_PLACE_MOUSE,FL_TRANSIENT,"Add a server");
	fl_do_forms();/*!=form->close);*/
	
}

static void add_server(FD_add *form, long data){
	Server *p, *p2;
	char *buf, no_nick_given=0;

	if( (p=(Server *)malloc(sizeof(Server))) ==NULL)
	       {err_ret("Mem error"); return;}

	
	buf=(char *)fl_get_choice_text(form->nicklist);
	#warning  (24.02.98) TODO typedef NickCount to char; type mismatch
	if(!buf || !(*buf) || (p->iNick= get_list_bylabel(buf))<0)
		p->iNick= iNickListCount>0?0:-1;
	
	p->servname=nextstr(fl_get_input(form->servername),1);
	if(!p->servname){
	  fl_ringbell(0);
	  berr_msg("Specify a server name");
	  free(p);return;
	}
	p->nick=clean(nextstr(fl_get_input(form->nick),1));
	if(!p->nick){
		no_nick_given=1;
		 p->nick=p->iNick>-1?aNickList[p->iNick].current->nick:Name;
	} 
	if(p->iNick>-1)
	if(!(aNickList[p->iNick].current= add_nick_to_list(p->iNick, p->nick)))
		err_sys("error");
	p->email=nextstr(fl_get_input(form->email),1);
	if(!p->email){
		p->email=(char *)malloc(sizeof(char)*(strlen(Name)+strlen(host)+3));
		sprintf(p->email, "%s@%s", Name, host);
	}
	buf=clean(fl_get_input(form->ircname));
	p->ircname=buf? strdup(buf): sula_NAME sula_VERSION" Tester";
	p->password= nextstr(fl_get_input(form->password),1);
	buf=(char *)fl_get_input(form->port);
	if( !buf ||  (p->port=atoi(buf))==0 ) p->port=DEFAULT_PORT;
	p->state=-1;
	p->fd=-1;
	if(data) /* editing entry */
	if(search_server_tree_byname(p->servname, p->port))
		if(!remove_server_from_tree(p->servname,p->port)) {
		  	berr_msg(   "%s (%d) Cant save. window connected to server",__FILE__,__LINE__);
			fl_ringbell(0);
			goto end;
	        }
	insert_server(&servTree, p, BY_NAME);
	if(!(p2=search_server_tree_byname(p->servname, p->port))){
		fl_ringbell(0);
		err_msg("%s (%d) Server recheck failed!", __FILE__,__LINE__);
	}
	else{
	     if(no_nick_given) fl_set_input(form->nick, p2->nick);
	      fl_trigger_object(server_tool->update);
	}
end:
	free(p->email); free(p);
}
	

static void edit(void){
	FD_add *form=create_form_add();
	int n;
	const char *buf;
	char port_[8], *servname;
	u_short port;
	Server *s;
	
	#ifndef NO_BUG
	server_tool->dismiss->u_ldata=1;
	#endif
	fl_set_cursor(server_tool->serverlist->window, XC_watch);
	fl_deactivate_form(server_tool->serverlist);
	n=fl_get_browser(server_tool->browser);
	if(n<1){
	     fl_set_object_label(server_tool->status, "Select a server first.");
     	    goto done;
       }
	buf=fl_get_browser_line(server_tool->browser,n);
	servname=(char *)malloc(sizeof(char)*strlen(buf));
	if(sscanf(buf,"%*s %s %hu", servname, &port)<2)
		/*if(sscanf(buf,"@b%*d. %s %hu",	servname, &port)<2)*/
		{
			char *txt=(char*)malloc(sizeof(char)*(strlen(buf)+16));
			sprintf(txt,"Invalid: %s",buf);
			fl_set_object_label(server_tool->status, txt);
			free(txt);
     	   		goto done;
		}
	s=search_server_tree_byname(servname, port);
	assert(s);
	if(iNickListCount>0){
		n=0;
	 	while(n<iNickListCount){
	 		if(aNickList[n].label)
			 	fl_addto_choice(form->nicklist,aNickList[n].label);
			n++;
	  	}
	}
	fl_set_choice_text(form->nicklist, aNickList[s->iNick].label);
	form->ircname->u_ldata=form->nick->u_ldata= \
		form->email->u_ldata=form->password->u_ldata= \
	form->servername->u_ldata=form->port->u_ldata=(long)XC_xterm;
	/*fl_set_object_prehandler(form->input_grp, set_cursor);*/
	fl_set_object_prehandler(form->nick, set_cursor);
	fl_set_object_prehandler(form->email, set_cursor);
	fl_set_object_prehandler(form->servername, set_cursor);
	fl_set_object_prehandler(form->port, set_cursor);
	fl_set_object_prehandler(form->ircname, set_cursor);
	fl_set_object_prehandler(form->password, set_cursor);
	form->done->u_ldata=(long)1;	/*edit*/
	fl_set_input(form->email,s->email? s->email:"");
	fl_set_input(form->nick, s->nick);
	fl_set_input(form->ircname, s->ircname?s->ircname:"");
	fl_set_input(form->servername, s->servname);
	fl_set_input(form->password,s->password?s->password:"");
	sprintf(port_,"%u", s->port);
	fl_set_input(form->port,port_);
	fl_set_form_atclose(form->add, dont_close_win, 0);
	fl_show_form(form->add,FL_PLACE_MOUSE,FL_TRANSIENT,"Edit server entry");
	while(fl_do_forms()!=form->close);
	return;

done:
	fl_reset_cursor(server_tool->serverlist->window);
	fl_activate_form(server_tool->serverlist);
	return;
}
 
static void disconnect(void){
	int browser_line;

	browser_line=fl_get_browser(server_tool->browser);
	if(browser_line<1){
	     fl_set_object_label(server_tool->status, "Select a server first");
     	    return;
       }
 	else{
		const char *buf;
		char servname[512];
		u_short port;

	    	buf=fl_get_browser_line(server_tool->browser, browser_line);
		if(sscanf(buf,"%*s %s %hu", servname, &port)<2)
		   /*if(sscanf(buf,"@b%*d. %s %hu", servname, &port)<2)*/
		   {
		     char *txt=(char*)malloc(sizeof(char)*(strlen(buf)+16));
		     sprintf(txt,"Invalid: %s",buf);
			fl_set_object_label(server_tool->status, txt);
			free(txt);
     	   		return;
		}
		fl_set_object_label(server_tool->status, "okay");
		close_server_connectionbyname(servname, port);
		/*fl_set_object_label(form->status, "Ready"); previous statement NEVER returns!*/
	}

}

static void connect_server(void){
	char *buf, servname[512];
	Server *s;
	int n;

	n=fl_get_browser(server_tool->browser); /* browser line*/
	if(n<1){
	     fl_set_object_label(server_tool->status, "Select a server first");
     	    return;
       }
       #ifndef NO_BUG
       /* there's a bug which cases pointer/keybrd focus to differ->SIGSEV.
       see sula_cb.c for more
       */
	if(server_tool->dismiss->u_ldata){
		fl_set_object_label(server_tool->status,
			"Please close and reopen this window.. a bug");
		fl_ringbell(0);
		return;
	}
	#endif
       if( (s=(Server *)malloc(sizeof(Server)))==NULL) /* no mem; quit */
       		err_sys("%s (%d) %s", __FILE__, __LINE__);
       buf=strdup(fl_get_browser_line(server_tool->browser, n));
       if( sscanf(buf,"%*s %s %hu", servname, &s->port) <2) 
           /*if(sscanf(buf,"@b%*d. %s %hu",  servname, &s->port)<2)*/
	   {
		char *txt=(char*)malloc(sizeof(char)*(strlen(buf)+16));
		sprintf(txt,"Invalid: %s.",buf);
		fl_set_object_label(server_tool->status,txt);
		free(txt);
		free(s);
		return;
	}
	s->servname=strdup(servname);
	sprintf(servname,"Connection to port %hu of %s initiated", 
	s->port,s->servname);
	fl_set_object_label(server_tool->status,servname);

	connect_to_server(s, NULL, NULL,0);
	free(s);

}

void add_server_cb(FL_OBJECT *ob, long data){
	FD_add *form=(FD_add *)ob->form->fdui;
	switch(data){
	case 0: add_server(form, ob->u_ldata); break;
	case 1:{
		fl_hide_form(form->add);
		fl_free_form(form->add);
		fl_reset_cursor(server_tool->serverlist->window);
		fl_activate_form(server_tool->serverlist);
		break;
	  }
	 default:break;
	}
}


void serverlist_cb(FL_OBJECT *ob, long data){
switch(data){
case 0:	/*connect*/
	connect_server();
	break;
case 1:
	disconnect();
	break;
case 2:
	add();
	break;
case 3:
	edit();
	break;
case 4:
	remove_server();
	break;
case 5:{	/* update*/
	char buf[512];
	fl_freeze_form(server_tool->serverlist);
	fl_clear_browser(server_tool->browser);
	i=1;
	sprintf(buf,"@N@f@C7%-2s. %-30s %-5s %-20s %-12s %-30s (%s)", 
	       "Nr", " Server","Port", "Nickname","Group","Address","IRC Name"); 
	     fl_addto_browser(server_tool->browser, buf);
	loadlist(servTree);
	fl_unfreeze_form(server_tool->serverlist);
	}
	break;
case 6:{
	char  *ptr;
	char buf[512];

	#ifndef NO_BUG
	server_tool->dismiss->u_ldata=1;
	#endif
	if( (ptr=getenv("HOME")) ) 
		sprintf(buf,"%s/%s/%s", ptr , P_HOME, P_SERVERS);
	else sprintf(buf,"./%s/%s", P_HOME, P_SERVERS);
	fl_set_cursor(server_tool->serverlist->window, XC_watch);
	fl_deactivate_form(server_tool->serverlist);
	ptr=getstr2("File name:",
		sula_NAME sula_VERSION": Save server list",buf, 1);
	fl_activate_form(server_tool->serverlist);
	fl_reset_cursor(server_tool->serverlist->window);
	ptr=clean(ptr); 
	if(!ptr) break;
	if(save_servers(ptr))
		 sprintf(buf,"Error: Cant write %s. %s", ptr, strerror(errno));
	else sprintf(buf,"server list saved as %s", ptr);
	fit_object_label(server_tool->status,buf);
	break;
	}
case 7:
	#ifndef NO_BUG
	server_tool->dismiss->u_ldata=0;
	#endif
	fl_hide_form(server_tool->serverlist);
	fl_free_form(server_tool->serverlist);
	server_tool = NULL;
	
	break;
default:break;
}/*switch*/
}


