/* idle_cb.c - activities for an idle client ..........
 * distributed as part of _ s u l a _
 * 
 * Author: Tano Fotang, 1998
 * 
 * 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 further information. 
 * 
 */



#include <forms.h>
#include <time.h>
#include "aux.h"
#include "sula.h"
#include "chanwin.h"
#include "global.h"
#include "dcc_gui.h"
#include "dcc.h"
#include "ignore.h"
#include "servers.h"
#include "lag.h"
#include "idle_cb.h"

#ifndef NOLAG
static void check_server_lag(Server *p){
	if(p){
		Server *s=search_server_tree_byname(p->servname,p->port);
		assert(s);
		check_server_lag(p->left);
		if(s->lag) {
			struct timeval t;
			gettimeofday(&t,NULL);
			update_lag_display(s,
				t.tv_sec- s->lag->when.tv_sec+
		    (float)((t.tv_usec- s->lag->when.tv_usec)/ 1000000.0),
				  (struct timeval *)0);
		}
		check_server_lag(p->right);
	}
}
#endif


static void check_ignore(void)
{
	Ignore *p = ignoreStart;
	time_t  t = time(NULL);

	while (p != ignoreEnd) {
		if (p->period == 0) {
			p = p->next;
			continue;
		}
		if ((p->starttime + 60 * p->period) < t) {
			Ignore *q = p->next;

			free(p->mask);
			if (q == ignoreEnd)
				ignoreEnd = p;
			else
				*p = *q;
			free(q);
		}
		else
			p = p->next;
	}
	return;
}
static void check_dcc_sent(int flag)
{

	time_t  t = time(NULL);

	if (flag) {
		ChatReqSent *p = chatsentStart;

		while (p != chatsentEnd)
			if (t > (p->starttime + dcc_timeout * 60))
				remove_sentchatreq(p->id);
			else
				p = p->next;
	}
	else {
		DCCFileS *q = filesendStart;

		while (q != filesendEnd)
			if (t > (q->starttime + dcc_timeout * 60))
				remove_file_offer(q->id);
			else
				q = q->next;
	}
	return;
}

static void check_dcc_recvd(int flag)
{
	time_t  t = time(NULL);

	if (flag) {
		ChatReqRecvd *q = chatreqStart;

		while (q != chatreqEnd)
			if (t > (q->starttime + dcc_timeout * 60)) {
				ChatReqRecvd *p = q->next;

				free(q->nick);
				free(q->email);
				if (p == chatreqEnd)
					chatreqEnd = q;
				else
					*q = *p;
				free(p);
				return;
			}
			else
				q = q->next;
	}
	else {
		DCCFileR *q = filegetStart;

		while (q != filegetEnd)
			if (t > (q->starttime + dcc_timeout * 60)) {
				DCCFileR *p = q->next;

				free(q->nick);
				free(q->email);
				free(q->filename);
				if (p == filegetEnd)
					filegetEnd = q;
				else
					*q = *p;
				free(p);
				return;
			}
			else
				q = q->next;
	}
}
extern ActiveDCC *aActiveDCC;
static void update_active_dcc_display(void)
{

	#if 1
	DCCFile *p = DCCfileStart;
	
	/*if(!(gflags&VERBOSE_CTCP)) return;*/
	while (p != DCCfileEnd){
		if(p->w>=0 && p->size>0 && p->read<p->size){
			char buf[20];
			float x=p->read * 100.0/p->size;
			struct timeval t;
			float dt;
			gettimeofday(&t,NULL);
			sprintf(buf,"%5.1f%%", x);
			fl_set_slider_value(aActiveDCC[p->w].form->slider,x);
			fl_set_object_label(aActiveDCC[p->w].form->slider,buf);
			dt=t.tv_sec-p->lasttime.tv_sec
			#if 1
			+
			(t.tv_usec-p->lasttime.tv_usec)/1000000.0
			#endif
			;
			if(dt==0) dt=1;
			sprintf(buf,"%10.1f kb/s",
			  (p->read- aActiveDCC[p->w].form->size->u_ldata)/(
			  dt * 1024));
			fl_set_object_label(aActiveDCC[p->w].form->speed,buf);
			aActiveDCC[p->w].form->size->u_ldata=p->read;
		}
		p = p->next;
	  }
	#endif
}
extern int idle_cb(XEvent * ev, void *junk)
{
	static int flag = 0;

	flag %= 9;
	switch (++flag) {
	    case 1:
		    check_ignore();
		    break;
	    case 2:
		    check_dcc_sent(0);
		    break;
	    case 3:
		    check_dcc_sent(1);
		    break;
	    case 4:
		    check_dcc_recvd(0);
		    break;
	    case 5:
		    check_dcc_recvd(1);
		    break;
	    case 6:
		    if(servFdTree)
		    if (ignore_form && (time(NULL) % 60) == 0) {
			    static char i = 0;

			    i %= 3;	/* kludge;stop flickering*/
			    if ((++i) == 1)
				    fl_call_object_callback(ignore_form->update);
		    }
		    break;
	    #ifndef NOLAG
	    case 7:
		send_lag_msg();
		break;
	    case 8:
		check_server_lag(servFdTree); /* update display */
		break;
	   #endif
	    case 9:
		    update_active_dcc_display();
		    break;
	    default:
		    break;
	}
	return 0;
}



