/** \file InfoDisplay.cc
 * \author Gabriel Montenegro <gmontenegro@users.sourceforge.net>
 * \date 10-14-04
 * \brief InfoDisplay class implementation
 *
 * Class implementation
 */

/*
 *  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.
 *
 *  This program 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 Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "InfoDisplay.h"
#include "Window.h"
#include "Config.h"
#include "Util.h"

InfoDisplay::InfoDisplay()
{
	m_bLastHaveOnlineTime = m_bLabelsDrawn = false;

	strData[0] = "Interface:";
	strData[1] = "IP Address:";
	strData[2] = "Top Receiving:";
	strData[3] = "Received Bytes:";
	strData[4] = "Received Packets:";
	strData[5] = "Errors on Receiving:";

	strData[6] = "Online Time:";
	strData[7] = "Top Transmission:";
	strData[8] = "Transmited Bytes:";
	strData[9] = "Transmited Packets:";
	strData[10] = "Errors on Transmission:";
}

InfoDisplay::~InfoDisplay()
{

}

void InfoDisplay::Draw(Interfaces & rInterfaces, bool bForce)
{
	Interface & rInterface = rInterfaces.getActive();
	Config * pConfig = Config::Instance();

	if(rInterface.haveOnlineTime() != m_bLastHaveOnlineTime)
	{
		bForce = true;
		m_bLastHaveOnlineTime = rInterface.haveOnlineTime();
	}

	if(pConfig->getValue("Information") == "On")
	{
		if(Window::ScreenLines() >= 10)
		{
 			if( Window::ScreenColumns() >= 72 )
			{
				if(!m_bLabelsDrawn || bForce)
					ShowLabels(rInterface, LeftRight);

				ShowInfo(rInterface, LeftRight, bForce);
			}
			else if( Window::ScreenColumns() >= 35 )
			{
				if(!m_bLabelsDrawn || bForce)
					ShowLabels(rInterface, Left);

				ShowInfo(rInterface, Left, bForce);
			}
		}

	}
	else
		m_bLabelsDrawn = false;

	rInterface.getWindow()->Refresh();
}

void InfoDisplay::FormatSize(unsigned long ulBytes, string & strOutput, bool bPerSecond)
{
	char cData[32];

  if(ulBytes >= 1099511627776)
		sprintf(cData, "%.2f TB%s", ((float)ulBytes) / 1099511627776, bPerSecond ? "/s" : "");
	if(ulBytes >= 1073741824 && ulBytes < 1099511627776)
		sprintf(cData, "%.2f GB%s", ((float)ulBytes) / 1073741824, bPerSecond ? "/s" : "");
	else if(ulBytes >= 1048576 && ulBytes < 1073741824 )
		sprintf(cData, "%.2f MB%s", ((float)ulBytes) / 1048576, bPerSecond ? "/s" : "");
	else if(ulBytes >= 1024 && ulBytes < 1048576)
		sprintf(cData, "%.2f KB%s", ((float)ulBytes) / 1024, bPerSecond ? "/s" : "");
	else
		sprintf(cData, "%ld B%s", ulBytes, bPerSecond ? "/s" : "");

	strOutput = cData;
}

void InfoDisplay::FormatPacket(unsigned long ulPackets, string & strOutput, bool bPerSecond)
{
	char cData[32];

  if(ulPackets >= 1000000000000)
		sprintf(cData, "%.2f TP%s", ((double)ulPackets) / 1000000000000, bPerSecond ? "/s" : "");
	if(ulPackets >= 1000000000 && ulPackets < 1000000000000)
		sprintf(cData, "%.2f GP%s", ((float)ulPackets) / 1000000000, bPerSecond ? "/s" : "");
	else if(ulPackets >= 1000000 && ulPackets < 1000000000 )
		sprintf(cData, "%.2f MP%s", ((float)ulPackets) / 1000000, bPerSecond ? "/s" : "");
	else if(ulPackets >= 1000 && ulPackets < 1000000)
		sprintf(cData, "%.2f KP%s", ((float)ulPackets) / 1000, bPerSecond ? "/s" : "");
	else
		sprintf(cData, "%ld P%s", ulPackets, bPerSecond ? "/s" : "");

	strOutput = cData;
}

void InfoDisplay::ShowLabels(Interface & rInterface, eDisplayInfo eInfo)
{
	Config * pConfig = Config::Instance();
	Window * pWindow = rInterface.getWindow();
	int iX, iY;

	pWindow->ChangeColor(TextWhite);

	// LEFT LABELS

 	if(eInfo == Left || eInfo == LeftRight)
	{
		iY = (int)(Window::ScreenLines() - 8);
		iX = (int)(Window::ScreenColumns() / 10);

		// Interface
		pWindow->MoveCursor(iY++, iX);
		pWindow->PutString(strData[0]);
		// IP Address
		pWindow->MoveCursor(iY++, iX);
		pWindow->PutString(strData[1]);
		// Top Speed per Second
		pWindow->MoveCursor(iY++, iX);
		pWindow->PutString(strData[2]);
		// Received Bytes
		pWindow->MoveCursor(iY++, iX);
		pWindow->PutString(strData[3]);
		// Received Packets
		pWindow->MoveCursor(iY++, iX);
		pWindow->PutString(strData[4]);
		// Errors on Receiving
		pWindow->MoveCursor(iY++, iX);
		pWindow->PutString(strData[5]);
	}

	// RIGHT LABELS

	if(eInfo == LeftRight)
	{
		iY = (int)(Window::ScreenLines() - 7);
		iX = (int)(Window::ScreenColumns() / 2);

		// Online Time
		if(rInterface.haveOnlineTime())
		{
			pWindow->MoveCursor(iY, iX);
	    pWindow->PutString(strData[6]);
		}
		else
		{
			pWindow->MoveCursor(iY, iX);
			pWindow->HorizontalLine(32, strData[6].length());
		}

		iY++;

		// Top Packets per Second
		pWindow->MoveCursor(iY++, iX);
		pWindow->PutString(strData[7]);
		// Transmited Bytes
		pWindow->MoveCursor(iY++, iX);
		pWindow->PutString(strData[8]);
		// Transmited Packets
		pWindow->MoveCursor(iY++, iX);
		pWindow->PutString(strData[9]);
		// Errors on Transmission
		pWindow->MoveCursor(iY++, iX);
		pWindow->PutString(strData[10]);
	}

	m_bLabelsDrawn = true;
}

void InfoDisplay::ShowInfo(Interface & rInterface, eDisplayInfo eInfo, bool bForce)
{
	Config * pConfig = Config::Instance();
	Window * pWindow = rInterface.getWindow();
	InterfaceData & rData = rInterface.getData();
	int iX, iY;
	int iInitialX = (Window::ScreenColumns() / 10);
	string strBytes;
  string strPackets;

	pWindow->ChangeColor(TextCyan);

	// LEFT INFORMATION

	if(eInfo == Left || eInfo == LeftRight)
	{
		// Interface
		iY = (int)(Window::ScreenLines() - 8);

		if(m_strLastInterface != rInterface.getInterface() || bForce)
		{
			iX = iInitialX + strData[0].length() + 1;

			pWindow->MoveCursor(iY, iX);
			pWindow->HorizontalLine(32, iLastDataSize[0]);
			iLastDataSize[0] = rInterface.getInterface().length();
			pWindow->PutString(rInterface.getInterface());

			m_strLastInterface = rInterface.getInterface();
		}

		iY++;

		// IP Address
		if(m_strLastIPAddress != rInterface.getIPAddress() || bForce)
		{
			iX = iInitialX + strData[1].length() + 1;

			pWindow->MoveCursor(iY, iX);
			pWindow->HorizontalLine(32, iLastDataSize[1]);
			iLastDataSize[1] = rInterface.getIPAddress().length();
			pWindow->PutString(rInterface.getIPAddress());

			m_strLastIPAddress = rInterface.getIPAddress();
		}

		iY++;

		// Top In Bytes per Second
		if(m_ulLastTopInBytesSecond != rInterface.getTopInBytesSecond() || bForce)
		{
			iX = iInitialX + strData[2].length() + 1;

			pWindow->MoveCursor(iY, iX);
			FormatSize(rInterface.getTopInBytesSecond(), strBytes, true);
			pWindow->HorizontalLine(32, iLastDataSize[2]);
			iLastDataSize[2] = strBytes.length();
			pWindow->PutString(strBytes);

			m_ulLastTopInBytesSecond = rInterface.getTopInBytesSecond();
		}

		iY++;

		// Received Bytes
		if(m_cLastData.getReceivedBytes() != rData.getReceivedBytes() || bForce)
		{
			iX = iInitialX + strData[3].length() + 1;

			pWindow->MoveCursor(iY, iX);
			FormatSize(rData.getReceivedBytes(), strBytes, false);
			pWindow->HorizontalLine(32, iLastDataSize[3]);
			iLastDataSize[3] = strBytes.length();
			pWindow->PutString(strBytes);

			m_cLastData.setReceivedBytes(rData.getReceivedBytes());
		}

		iY++;

		// Received Packets
	  if(m_cLastData.getReceivedPackets() != rData.getReceivedPackets() || bForce)
		{
			iX = iInitialX + strData[4].length() + 1;

			pWindow->MoveCursor(iY, iX);
	    FormatPacket(rData.getReceivedPackets(), strPackets, false);
	    pWindow->HorizontalLine(32, iLastDataSize[4]);
			iLastDataSize[4] = strPackets.length();
			pWindow->PutString(strPackets);

			m_cLastData.setReceivedPackets(rData.getReceivedPackets());
		}

		iY++;

		// Receiving Errors
	  if(m_cLastData.getReceivingErrors() != rData.getReceivingErrors() || bForce)
		{
			iX = iInitialX + strData[5].length() + 1;

			pWindow->MoveCursor(iY, iX);
			pWindow->PutUnsignedLong(rInterface.getData().getReceivingErrors());

			m_cLastData.setReceivingErrors(rData.getReceivingErrors());
		}
	}

	// RIGHT INFORMATION

	if(eInfo == LeftRight)
	{
		iInitialX = (Window::ScreenColumns() / 2);
		iY = (int)(Window::ScreenLines() - 7);

		// Online time
		iX = (iInitialX + strData[6].length() + 1);

		if(rInterface.haveOnlineTime())
		{
			if(m_strLastOnlineTime != rInterface.getOnlineTime() || bForce)
			{
				pWindow->MoveCursor(iY, iX);
				pWindow->PutString(rInterface.getOnlineTime());

				iLastDataSize[6] = rInterface.getOnlineTime().length();
				m_strLastOnlineTime = rInterface.getOnlineTime();
			}
		}
		else
		{
			if(bForce)
			{
				pWindow->MoveCursor(iY, iX);
				pWindow->HorizontalLine(32, iLastDataSize[6]);

				m_strLastOnlineTime = rInterface.getOnlineTime();
			}
		}

		iY++;

		// Top Out Bytes per Second
		if(m_ulLastTopOutBytesSecond != rInterface.getTopOutBytesSecond() || bForce)
		{
			iX = (iInitialX + strData[7].length() + 1);

			pWindow->MoveCursor(iY, iX);
	    FormatSize(rInterface.getTopOutBytesSecond(), strBytes, true);
	    pWindow->HorizontalLine(32, iLastDataSize[7]);
			iLastDataSize[7] = strBytes.length();
			pWindow->PutString(strBytes);

			m_ulLastTopOutBytesSecond = rInterface.getTopOutBytesSecond();
		}

		iY++;

		// Sent Bytes
	  if(m_cLastData.getSentBytes() != rData.getSentBytes() || bForce)
	  {
			iX = (iInitialX + strData[8].length() + 1);

			pWindow->MoveCursor(iY, iX);
			FormatSize(rData.getSentBytes(), strBytes, false);
			pWindow->HorizontalLine(32, iLastDataSize[8]);
			iLastDataSize[8] = strBytes.length();
			pWindow->PutString(strBytes);

			m_cLastData.setSentBytes(rData.getSentBytes());
		}

		iY++;

		// Sent Packets
		if(m_cLastData.getSentPackets() != rData.getSentPackets() || bForce)
		{
			iX = (iInitialX + strData[9].length() + 1);

			pWindow->MoveCursor(iY, iX);
	    FormatPacket(rData.getSentPackets(), strPackets, false);
	    pWindow->HorizontalLine(32, iLastDataSize[9]);
			iLastDataSize[9] = strPackets.length();
			pWindow->PutString(strPackets);

			m_cLastData.setSentPackets(rData.getSentPackets());
		}

		iY++;

		// Sent Errors
		if(m_cLastData.getSendingErrors() != rData.getSendingErrors() || bForce)
		{
			iX = (iInitialX + strData[10].length() + 1);

			pWindow->MoveCursor(iY, iX);
			pWindow->PutUnsignedLong(rInterface.getData().getSendingErrors());

			m_cLastData.setSendingErrors(rData.getSendingErrors());
		}
	}
}
