/* 
 *  Ths code in this file is part of tcptrack. For more information see
 *    http://www.rhythm.cx/~steve/devel/tcptrack
 *
 *     Copyright (C) Steve Benson - 2003
 *
 *  tcptrack 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, or (at your
 *  option) any later version.
 *   
 *  tcptrack is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *  
 */
#include "TextUI.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "util.h"
#include "Logger.h"
#include "defs.h"

extern Logger *logger;

TextUI::TextUI( TCContainer *c )
{
	container = c;
	WINDOW *w=initscr();
	int x,y;
	getmaxyx(w,y,x);
	size_x=x;
	size_y=y;
	bottom=y;
	
	// set up & start displayer thread
	run_displayer = true;
	int rc = pthread_create(&displayer_tid,NULL,displayer_thread_func,this);
	if( rc )
	{
		perror("pthread_create");
		assert(false);
	}
}

TextUI::~TextUI()
{
	endwin();
}

void TextUI::displayer_run()
{
	struct timespec t;
	t.tv_sec=0;
	t.tv_nsec=DISPLAY_REFRESH;

	while( run_displayer )
	{
		container->lock();
		drawui();
		container->unlock();
		nanosleep(&t,NULL);
	}
}

void TextUI::drawui()
{
	int row=1;
	
	erase();

	attron(A_REVERSE);
	move(0,0);
	printw("                                                                               ");

	move(0,1);
	printw("Client");
	move(0,23);
	printw("Server");
	move(0,45);
	printw("State");
	move(0,58);
	printw("Idle");
	move(0,63);
	printw("A");
	move(0,65);
	printw("Speed");

	attroff(A_REVERSE);



	move(1,0);

	SortedIterator i = container->getSortedIterator();
	i.sort();
	while( TCPConnection *ic=i.getNext() )
	{
		if( row > bottom-2 )
		{
			move(bottom-1,2);
			printw("[ Display Truncated ]");
			break;
		}
		
		if(   (ic->getState() == TCP_STATE_CLOSED || ic->getState() == TCP_STATE_RESET)
		   && time(NULL) - ic->getLastPktTimestamp() > CLOSED_PURGE )
		{
			continue;
		}
		
		char *srcAddr = in_addr2ascii(ic->getSrcAddr());
		char *dstAddr = in_addr2ascii(ic->getDstAddr());
		int srcPort = ntohs(ic->getSrcPort());
		int dstPort = ntohs(ic->getDstPort());
		
		move(row,1);
		printw("%s:%d",srcAddr,srcPort);
		move(row,23);
		printw("%s:%d",dstAddr,dstPort);

		move(row,45);
		printw("             ");
		move(row,45);
		if( ic->getState() == TCP_STATE_SYN_SYNACK )
			printw("SYN_SENT");
		else if( ic->getState() == TCP_STATE_SYNACK_ACK )
			printw("SYN|ACK-ACK");
		else if( ic->getState() == TCP_STATE_UP )
			printw("ESTABLISHED");
		else if( ic->getState() == TCP_STATE_FIN_FINACK )
			printw("CLOSING");
		else if( ic->getState() == TCP_STATE_CLOSED )
			printw("CLOSED");
		else if( ic->getState() == TCP_STATE_RESET )
			printw("RESET");
		
		move(row,58);
		if( ic->getIdleSeconds() > 9999 ) 
			printw("9999");
		else
			printw("%d",ic->getIdleSeconds());
		
		move(row,63);
		if( ic->activityToggle() )
			printw("*");
		else
			printw(" ");

		move(row,65);
		int Bps = ic->getPayloadBytesPerSecond();
		assert(Bps>=0);
		
		if( Bps < 1024 )
			printw("%d B/s",Bps);
		if( Bps >= 1024 && Bps < 1024*1024 )
			printw("%d KB/s",Bps/1024);
		if( Bps >= 1024*1024 )
			printw("%d MB/s",Bps/(1024*1024));
		if( Bps > 99999999 ) // not enough room to display it
			printw("LUDICROUS");
		
		free(srcAddr); 
		free(dstAddr); 
		
		row++;
	}
	refresh();
}

/////////

void *displayer_thread_func( void *arg )
{
	TextUI *ui = (TextUI *) arg;
	ui->displayer_run();
	return NULL;
}

