/*
 *	This file was originally part of Matt Smith's
 *	mICQ, and is now included in GTK-ICQ.  Below
 *	are the original authors and contributors:
 *
 *	Original Author:
 *		 Matthew Smith		04/23/1998
 *		 
 *	Contributors:
 *
 *		airog			04/13/1998
 */

#include "gtkicq.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <unistd.h>
#include <termios.h>

#include "pixmaps.h"

static char rcfile[256];


/* Convets a Status to a string */
char *Convert_Status_2_Str( int status )
{
	if ( STATUS_OFFLINE == status ) /* this because -1 & 0xFFFF is not -1 */
	{
		return "Offline";
	}
   
	switch ( status & 0xffff )
	{
	case STATUS_ONLINE:
		return "Online";
		break;
	case STATUS_DND:
		return "Do not disturb";
		break;
	case STATUS_AWAY:
		return "Away";
		break;
	case STATUS_OCCUPIED:
		return "Occupied";
		break;
	case STATUS_NA:
		return "Not available";
		break;
	case STATUS_INVISIBLE:
		return "Invisible";
		break;
	case STATUS_FREE_CHAT:
		return "Free for chat";
		break;
	default:
		return NULL;
		break;
	}
}


/* Convets a Status to a string (short version) */
char *Convert_Status_2_Short( int status )
{
	if ( STATUS_OFFLINE == status ) /* this because -1 & 0xFFFF is not -1 */
	{
		return "(OFF)";
	}
   
	switch ( status & 0xffff )
	{
		case STATUS_ONLINE:
			return "(ONLN)";
			break;
		case STATUS_DND:
			return "(DND)";
			break;
		case STATUS_AWAY:
			return "(AWAY)";
			break;
		case STATUS_OCCUPIED:
			return "(OCC)";
			break;
		case STATUS_NA:
			return "(N/A)";
			break;
		case STATUS_INVISIBLE:
			return "(INV)";
			break;
		case STATUS_FREE_CHAT:
			return "(FFC)";
			break;
		default:
			return NULL;
			break;
	}
}

/* Returns the status of 'new_status' as string */
char *Print_Status_Short( DWORD new_status  )
{
	if ( Convert_Status_2_Short( new_status ) != NULL )
	{
		return Convert_Status_2_Short( new_status );
	}
	else
	{
		return "(UNKN)";
	}
}

GdkPixmap *GetIcon_p( DWORD status )
{
	if ( STATUS_OFFLINE == status ) /* this because -1 & 0xFFFF is not -1 */
	{
		return icon_offline_pixmap;
	}
   
	switch ( status & 0xffff )
	{
	case STATUS_ONLINE:
		return icon_online_pixmap;
		break;
	case STATUS_DND:
		return icon_dnd_pixmap;
		break;
	case STATUS_AWAY:
		return icon_away_pixmap;
		break;
	case STATUS_OCCUPIED:
		return icon_occ_pixmap;
		break;
	case STATUS_NA:
		return icon_na_pixmap;
		break;
	case STATUS_INVISIBLE:
		return icon_inv_pixmap;
		break;
	case STATUS_FREE_CHAT:
		return icon_ffc_pixmap;
		break;
	default:
		return icon_offline_pixmap;
		break;
	}
}

GdkBitmap *GetIcon_b( DWORD status )
{
	if ( STATUS_OFFLINE == status ) /* this because -1 & 0xFFFF is not -1 */
	{
		return icon_offline_bitmap;
	}
   
	switch ( status & 0xffff )
	{
	case STATUS_ONLINE:
		return icon_online_bitmap;
		break;
	case STATUS_DND:
		return icon_dnd_bitmap;
		break;
	case STATUS_AWAY:
		return icon_away_bitmap;
		break;
	case STATUS_OCCUPIED:
		return icon_occ_bitmap;
		break;
	case STATUS_NA:
		return icon_na_bitmap;
		break;
	case STATUS_INVISIBLE:
		return icon_inv_bitmap;
		break;
	case STATUS_FREE_CHAT:
		return icon_ffc_bitmap;
		break;
	default:
		return icon_offline_bitmap;
		break;
	}
}
	

/* Returns the status of 'new_status' as string (short version) */
void Print_Status( DWORD new_status  )
{
	if ( Convert_Status_2_Str( new_status ) != NULL )
	{
		printf( "%s", Convert_Status_2_Str( new_status ) );
	}
	else
	{
		printf( "%08lX", new_status );
	}
}

/* Returns the name of a User otherwise the UIN */
int Print_UIN_Name( DWORD uin )
{
	int i;
   
	for ( i=0; i < Num_Contacts; i++ )
	{
		if ( Contacts[i].uin == uin )
		{
			break;
		}
	}

	if ( i == Num_Contacts )
	{
		return -1 ;
	}
	else
	{
		return i;
	}
}

char *Get_UIN_Name( DWORD uin, char *buf )
{
	int i;
   
	for ( i = 0; i < Num_Contacts; i++ )
	{ 
		if ( Contacts[i].uin == uin )
		{
			break;
		}
	}

	if ( i == Num_Contacts )
	{
		sprintf( buf, "%lu", uin );
	}
	else
	{
		sprintf( buf, "%s", Contacts[i].nick );
	}

	return buf;
}

/* Convert a name into a UIN from Contact List */
DWORD nick2uin( char *nick )
{
	int i;
	BOOL non_numeric = FALSE;
   
	for ( i=0; i< Num_Contacts; i++ )
	{
		if ( ! strncasecmp( nick, Contacts[i].nick, 19  ) )
		{
			if ( (S_DWORD) Contacts[i].uin > 0 )
			{
				return Contacts[i].uin;
			}
			else
			{
				return -Contacts[i].uin; /* alias */
			}
		}
	}

	for ( i=0; i < strlen( nick ); i++ )
	{
		if ( ! isdigit( GPOINTER_TO_INT( nick[i] ) ) )
		{
			non_numeric = TRUE;
			break;
		}
	}

	if ( non_numeric )
	{
		return -1; /* not found and not a number */
	}
	else
	{
		return atoi( nick );
	}
}

/*******************************************************
Gets config info from the rc file in the users home 
directory.
********************************************************/
void Get_Unix_Config_Info( void )
{
	char filename[ 256 ];
	char *path;
	FD_T rcf;

#ifdef TRACE_FUNCTION
	printf( "Get_Unix_Config_Info\n" );
#endif

	path = getenv( "HOME" );
	strcpy( filename, path );
	strcat( filename, "/" );

	strcpy( rcfile, filename );
	strcat( rcfile, ".icq/gtkicqrc" );

	rcf = open( rcfile, O_RDONLY );

	if ( rcf == -1 )
	{
		if ( errno == ENOENT ) /* file not found */
		{
			Initalize_RC_File();
			Read_RC_File();
		}
		else
		{
			perror( "Error reading config file exiting " );
			exit( 1 );
		}
	}
	else
	{
		Read_RC_File();
	}

	close( rcf );
}

void Print_IP( DWORD uin )
{
	int i;
	DWORD t;

	for ( i=0; i< Num_Contacts; i++ )
	{
		if ( Contacts[i].uin == uin )
		{
			if ( Contacts[i].current_ip != -1L )
			{
				t = Contacts[i].current_ip;
				if ( Int_End )
					printf( "%u.%u.%u.%u",(BYTE) (t>>24),(BYTE) (t>>16),(BYTE) (t>>8),(BYTE) (t) );
				else
					printf( "%u.%u.%u.%u",(BYTE) (t),(BYTE) (t>>8),(BYTE) (t>>16),(BYTE) (t>>24) );
			}
			else
			{
				printf( "unknown" );
			}
			return;
		}
	}
	printf( "unknown" );
}

/************************************************
Gets the TCP port of the specified UIN
************************************************/
DWORD Get_Port( DWORD uin )
{
	int i;

	for ( i=0; i< Num_Contacts; i++ )
	{
		if ( Contacts[i].uin == uin )
		{
			return Contacts[i].port;
		}
	}
	return -1L;
}

/********************************************
Converts an intel endian character sequence to
a DWORD
*********************************************/
DWORD Chars_2_DW( unsigned char *buf )
{
	DWORD i;

	i= buf[3];
	i <<= 8;
	i+= buf[2];
	i <<= 8;
	i+= buf[1];
	i <<= 8;
	i+= buf[0];

	return i;
}

/********************************************
Converts an intel endian character sequence to
a WORD
*********************************************/
WORD Chars_2_Word( unsigned char *buf )
{
	WORD i;

	i= buf[1];
	i <<= 8;
	i += buf[0];

	return i;
}

/********************************************
Converts a DWORD to
an intel endian character sequence 
*********************************************/
void DW_2_Chars( unsigned char *buf, DWORD num )
{
	buf[3] = ( unsigned char ) ((num)>>24)& 0x000000FF;
	buf[2] = ( unsigned char ) ((num)>>16)& 0x000000FF;
	buf[1] = ( unsigned char ) ((num)>>8)& 0x000000FF;
	buf[0] = ( unsigned char ) (num) & 0x000000FF;
}

/********************************************
Converts a WORD to
an intel endian character sequence 
*********************************************/
void Word_2_Chars( unsigned char *buf, WORD num )
{
	buf[1] = ( unsigned char ) (((unsigned)num)>>8) & 0x00FF;
	buf[0] = ( unsigned char ) ((unsigned)num) & 0x00FF;
}

void Time_Stamp( void )
{
	struct tm *thetime;
	time_t p;

	p=time(NULL);
	thetime=localtime(&p);
}

void Add_User( SOK_T sok, DWORD uin, char *name )
{
	int cx;

#ifdef TRACE_FUNCTION
	printf( "Add_User\n" );
#endif

	for( cx = 0; cx < Num_Contacts; cx ++ )
	{
		if( uin == Contacts[ cx ].uin )
			return;
	}

	Contacts[ Num_Contacts ].uin = uin;
	Contacts[ Num_Contacts ].icon_p = icon_offline_pixmap;
	Contacts[ Num_Contacts ].icon_b = icon_offline_bitmap;
	Contacts[ Num_Contacts ].log_window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
	gtk_widget_set_usize( Contacts[ Num_Contacts ].log_window, 625, 250 );
	gtk_signal_connect( GTK_OBJECT( Contacts[ Num_Contacts ].log_window ), "delete_event",
	                    GTK_SIGNAL_FUNC( gtk_widget_hide_on_delete ),
	                    NULL );
	Contacts[ Num_Contacts ].log_list = gtk_text_new( NULL, NULL );
	gtk_text_set_editable( GTK_TEXT( Contacts[ Num_Contacts ].log_list ),
	                       FALSE );
	gtk_container_add( GTK_CONTAINER( Contacts[ Num_Contacts ].log_window ),
	                   Contacts[ Num_Contacts ].log_list );
	gtk_widget_show( Contacts[ Num_Contacts ].log_list );
	Contacts[ Num_Contacts ].message = NULL;
	Contacts[ Num_Contacts ].messages = 0;
	Contacts[ Num_Contacts ].need_update = 1;
	Contacts[ Num_Contacts ].status = STATUS_OFFLINE;
	Contacts[ Num_Contacts ].last_status = STATUS_OFFLINE;
	Contacts[ Num_Contacts ].last_time = -1L;
	Contacts[ Num_Contacts ].current_ip = -1L;
	Contacts[ Num_Contacts ].port = 0;
	Contacts[ Num_Contacts ].sok = (SOK_T ) -1L;
	Contacts[ Num_Contacts ].invis_list = FALSE;
	Contacts[ Num_Contacts ].lb_index = 2 + Num_Contacts;
	Contacts[ Num_Contacts ].gdk_input_tag = 0;
	Contacts[ Num_Contacts ].chat_seq = 0;
	Contacts[ Num_Contacts ].chat_sok = 0;
	Contacts[ Num_Contacts ].chat_active = FALSE;
	Contacts[ Num_Contacts ].chat_active2 = FALSE;
	Contacts[ Num_Contacts ].chat_port = 0;
	Contacts[ Num_Contacts ].chat_bg_red =
	Contacts[ Num_Contacts ].chat_bg_green =
	Contacts[ Num_Contacts ].chat_bg_blue = 255;
	Contacts[ Num_Contacts ].chat_fg_red =
	Contacts[ Num_Contacts ].chat_fg_green =
	Contacts[ Num_Contacts ].chat_fg_blue = 0;
	Contacts[ Num_Contacts ].tcp_gdk_input = 0;
	Contacts[ Num_Contacts ].chat_gdk_input = 0;
	memcpy( Contacts[ Num_Contacts ].nick, name, sizeof( Contacts->nick )  );
	snd_contact_list( sok );

	Contacts[ Num_Contacts ].info_uin = gtk_entry_new();
	Contacts[ Num_Contacts ].info_ip = gtk_entry_new();
	Contacts[ Num_Contacts ].info_nick = gtk_entry_new();
	Contacts[ Num_Contacts ].info_city = gtk_entry_new();
	Contacts[ Num_Contacts ].info_state = gtk_entry_new();
	Contacts[ Num_Contacts ].info_sex = gtk_entry_new();
	Contacts[ Num_Contacts ].info_phone = gtk_entry_new();
	Contacts[ Num_Contacts ].info_homepage = gtk_entry_new();
	Contacts[ Num_Contacts ].info_about = gtk_entry_new();
	Contacts[ Num_Contacts ].info_fname = gtk_entry_new();
	Contacts[ Num_Contacts ].info_lname = gtk_entry_new();
	Contacts[ Num_Contacts ].info_email = gtk_entry_new();
	Contacts[ Num_Contacts ].info_auth = gtk_entry_new();
	Contacts[ Num_Contacts ].pdata = NULL;

	Num_Contacts++;
	send_info_req( sok, uin );
	snd_contact_list( sok );
}
