/************************************************************************/
/* Copyright 1992 - 1997 MBARI						*/
/************************************************************************/
/* $Header: peercall.c,v 2.0 95/09/20 14:22:58 hebo Exp $		*/
/* Summary  : Callbacks for DM Peer Viewer				*/
/* Filename : peercall.c						*/
/* Author   : Bob Herlien (rah)						*/
/* Project  : Tiburon							*/
/* $Revision: 2.0 $							*/
/* Created  : 05/27/97 from rov.c					*/
/************************************************************************/
/* Modification History:						*/
/* $Log:	peercall.c,v $
   27may97, rah, created from rov.c
*/
/************************************************************************/

#include <mbari/types.h>
#include <mbari/const.h>
#include <Xm/Xm.h>
#include <X11/Intrinsic.h>
#include "peerview.h"
#include <time.h>
typedef Void 	*SEM_ID;		/* So we don't have to include	*/
					/*  all the VxWorks garbage	*/
#include <datamgr.h>
#include <sys/socket.h>			/* Stuff for gethostbyaddr()	*/
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>

#define PEERLIST_STRING_SIZE	1024
#define PEERLIST_NAMESIZE	32


/********************************/
/*	External Data		*/
/********************************/

Extern XtAppContext	appcontext;	/* The application context	*/
Extern AppData		appdata;	/* Application-wide resources	*/
Extern Widget		peerWindow, peerList;
Extern char		buff[];		/* Misc buffer used application-wide*/


/********************************/
/*	Module Local Data	*/
/********************************/

MLocal Widget		peerClipWindow;
MLocal Int32		dmPeerSeqNo = -1;
MLocal Pixel		connectok_fg, connectok_bg;
MLocal char		peerListString[PEERLIST_STRING_SIZE];
MLocal char		*dmPeerStrings[] =
  { "Down", "Not Connected", "Booting", "Init Phase 1", "Initializing",
    "Init Sent", "Init Rcvd", "Connected" };

MLocal TimeoutStruct	peerTimeoutStruct = 
{ &appdata.dm_update, 0 };


/************************************************************************/
/* Function    : peerStatusString					*/
/* Purpose     : Get Peer name and status string			*/
/* Inputs      : Peer inaddr, status, ptr to place to return name	*/
/* Outputs     : Ptr to status string					*/
/************************************************************************/
    char *
peerStatusString( InAddr addr, Int32 status, char *np, Nat32 nmlen )
{
    Reg struct hostent	*hp;
    Reg char		*p;
    Int32		stringIndex;
    struct in_addr	inaddr;
    char		nodename[PEERLIST_NAMESIZE];

    inaddr.s_addr = addr;    
    if ( (hp = gethostbyaddr((char *)&inaddr, sizeof(inaddr), AF_INET))
	 == (struct hostent *)NULL )
	strncpy( np, inet_ntoa(inaddr), nmlen );
    else
    {
	strncpy( np, hp->h_name, nmlen );
	if ( (p = strchr(np, '.')) != NULL )
	    *p = '\0';
    }

    stringIndex = status + 1;

    return( (stringIndex < XtNumber(dmPeerStrings)) ?
	    dmPeerStrings[stringIndex] : "Unknown" );

} /* peerStatusString() */


/************************************************************************/
/* Function    : updatePeerStatus					*/
/* Purpose     : Update DM Peer Connection Status List			*/
/* Inputs      : Pointer to TimeoutStruct				*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updatePeerStatus( TimeoutStruct *tp )
{
    DmPeerSts		status[MAX_PEERS];
    Reg Nat32		i, n;
    Reg char		*sts;
    Reg Int32		newPeerSeqNo;
    Nat32		npeers;
    XmString		str;
    Pixel		fg, bg;
    char		nodename[PEERLIST_NAMESIZE];

    npeers = MAX_PEERS;
    if ( (newPeerSeqNo = dm_peer_status(status, &npeers)) == dmPeerSeqNo )
	return;

    dmPeerSeqNo = newPeerSeqNo;
    fg = connectok_fg;
    bg = connectok_bg;

    for ( i = n = 0; i < npeers; i++ )
	if ( status[i].peer_addr != (InAddr)0 )
	{
	    sts = peerStatusString( status[i].peer_addr, status[i].peer_state,
				    nodename, PEERLIST_NAMESIZE );

	    n += sprintf(peerListString + n, "%-16s %s\n", nodename, sts);
	    if ( status[i].peer_state != DMP_CONN )
	    {
		fg = appdata.connect_fg;
		bg = appdata.connect_bg;
	    }
	}

    if ( n == 0 )
	strcpy( peerListString, "None" );
    else 
	peerListString[n-1] = '\0';		/* Remove trailing '\n'	*/

    str = XmStringCreateLtoR(peerListString, XmSTRING_DEFAULT_CHARSET);

    XtVaSetValues( peerList, XmNlabelString, str,
		   XmNforeground, fg, XmNbackground, bg, NULL );

    XtVaSetValues( peerClipWindow, XmNbackground, bg, NULL );

    XmStringFree(str);

    tp->tmoutId = XtAppAddTimeOut( appcontext, *tp->timeout,
				   (XtTimerCallbackProc)updatePeerStatus, tp );

} /* updatePeerStatus() */


/************************************************************************/
/* Function    : initialize						*/
/* Purpose     : Initialize function for peer viewer			*/
/* Inputs      : None							*/
/* Outputs     : None							*/
/************************************************************************/
    Void
initialize( Void )
{
    XtVaGetValues( peerList, XmNforeground, &connectok_fg,
			     XmNbackground, &connectok_bg, NULL );

    XtVaGetValues( peerWindow, XmNclipWindow, &peerClipWindow, NULL );

    updatePeerStatus( &peerTimeoutStruct );

} /* initialize() */


/************************************************************************/
/* Function    : terminate						*/
/* Purpose     : Terminate ROV User Interface				*/
/* Inputs      : None							*/
/* Outputs     : None							*/
/* Comments    : Never returns						*/
/************************************************************************/
     Void
terminate( Void )
{
    if ( peerTimeoutStruct.tmoutId != 0 )
	XtRemoveTimeOut( peerTimeoutStruct.tmoutId );

    dm_task_exit(0);
    exit(0);

} /* terminate() */


/************************************************************************/
/* Function    : terminateCallback					*/
/* Purpose     : Callback for Close Window user action on Main window	*/
/* Inputs      : Widget, unused pointer, unused callback struct		*/
/* Outputs     : None							*/
/* Comments    : Never returns						*/
/************************************************************************/
     Void
terminateCallback( Widget w, XtPointer unused, XmAnyCallbackStruct *cbs )
{
    terminate();

} /* terminateCallback() */
