/** \file GraphDecorator.cc
 * \author Gabriel Montenegro <gmontenegro@users.sourceforge.net>
 * \date 10-14-04
 * \brief GraphDecorator 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 "GraphDecorator.h"
#include "Config.h"

GraphDecorator::GraphDecorator(Display * pDisplay) : Decorator(pDisplay)
{
	m_ullLastReceived = m_ullLastSent = 0;

	m_Graph.setIntersectionColor(BlockGreen);
	m_Graph.setInColor(BlockGreen);
	m_Graph.setOutColor(BlockYellow);
	m_Graph.setClearColor(TextBlack);
	m_Graph.setTextColor(TextWhite);

	m_Graph.setPosition(2, 1);
}

GraphDecorator::~GraphDecorator()
{

}

void GraphDecorator::Draw(Interfaces & rInterfaces, bool bForce)
{
	Interface & rInterface = rInterfaces.getActive();
	bool bDrawn = rInterface.isDrawn();

	DrawGraph(rInterface);
	DrawStats(rInterface);

	Decorator::Draw(rInterfaces, bForce);
}

void GraphDecorator::DrawStats(Interface & rInterface)
{
	Config * pConfig = Config::Instance();
	Window * pWindow = rInterface.getWindow();
	char cInFormat[64] = { 0 };
	char cOutFormat[64] = { 0 };
	char cFormat[128] = { 0 };

	if(pConfig->getValue("Information") == "On")
	{
		if(Window::ScreenLines() < 14 || Window::ScreenColumns() < 45)
			return;
	}
	else
	{
		if(Window::ScreenLines() < 7 || Window::ScreenColumns() < 45)
			return;
	}

	pWindow->ChangeColor(TextBlack);
	pWindow->MoveCursor(m_Graph.getHeight() + m_Graph.getX() + 2, m_Graph.getY() + 1);
	pWindow->HorizontalLine(32, m_Graph.getWidth());

	if(rInterface.isActive())
	{
		InterfaceData & rData = rInterface.getHistoryLastData();
		unsigned long ulInBytes = rData.getReceivedBytes();
		unsigned long ulOutBytes = rData.getSentBytes();

    if(ulInBytes >= 1073741824)
			sprintf(cInFormat, "[ %.2f GB/s in ]", ((float)ulInBytes) / 1073741824);
		else if((ulInBytes >= 1048576) && (ulInBytes < 1073741824))
			sprintf(cInFormat, "[ %.2f MB/s in ]", ((float)ulInBytes) / 1048576);
		else if((ulInBytes >= 1024) && (ulInBytes < 1048576))
			sprintf(cInFormat, "[ %.2f KB/s in ]", ((float)ulInBytes) / 1024);
		else if((ulInBytes > 0) && (ulInBytes < 1024))
			sprintf(cInFormat, "[ %ld B/s in ]", ulInBytes);
		else
			sprintf(cInFormat, "[ no in ]");


		if(ulOutBytes >= 1073741824)
			sprintf(cOutFormat, "[ %.2f GB/s out ]", ((float)ulOutBytes) / 1073741824);
		else if((ulOutBytes >= 1048576) && (ulOutBytes < 1073741824))
			sprintf(cOutFormat, "[ %.2f MB/s out ]", ((float)ulOutBytes) / 1048576);
		else if((ulOutBytes >= 1024) && (ulOutBytes < 1048576))
			sprintf(cOutFormat, "[ %.2f KB/s out ]", ((float)ulOutBytes) / 1024);
		else if((ulOutBytes > 0) && (ulOutBytes < 1024))
			sprintf(cOutFormat, "[ %ld B/s out ]", ulOutBytes);
		else
			sprintf(cOutFormat, "[ no out ]");

		sprintf(cFormat, "%s  %s", cInFormat, cOutFormat);

		pWindow->ChangeColor(TextCyan);
		pWindow->MoveCursor(m_Graph.getHeight() + m_Graph.getX() + 2, (int)(Window::ScreenColumns() / 2) - (strlen(cFormat) / 2));
		pWindow->PutString(cFormat);

		pWindow->ChangeColor(TextGreen, A_BOLD);
		pWindow->MoveCursor(m_Graph.getHeight() + m_Graph.getX(), (int)8);
		pWindow->PutString("[ ON ] ");

	}
	else
	{
		pWindow->ChangeColor(TextRed, A_BOLD);
		pWindow->MoveCursor(m_Graph.getHeight() + m_Graph.getX(), (int)8);
		pWindow->PutString("[ OFF ]");

	}
}

void GraphDecorator::DrawGraph(Interface & rInterface)
{
	Config * pConfig = Config::Instance();
	deque<InterfaceData> & rHistory = rInterface.getHistory();
	string strValue;
	long long llReceivedBytes = 0, llSentBytes = 0;
	int iPeriodCount = 1;
	unsigned int uiPeriod = atoi((pConfig->getValue("GraphPeriod")).c_str());
	bool bScaleInfo = true;

	if(pConfig->getValue("Information") == "On")
	{
		m_Graph.setArea(Window::ScreenColumns() - 4, Window::ScreenLines() - 14);

		if(Window::ScreenLines() < 17 || Window::ScreenColumns() < 15)
		{
			m_Graph.setArea(0, 0);
			return;
		}
	}
	else
	{
		m_Graph.setArea(Window::ScreenColumns() - 4, Window::ScreenLines() - 7);

		if(Window::ScreenLines() < 10 || Window::ScreenColumns() < 15)
		{
			m_Graph.setArea(0, 0);
			return;
		}
	}

	if(uiPeriod <= 0)
		uiPeriod = 1;

	m_Graph.lstData.clear();

	for(deque<InterfaceData>::iterator itHistory = rHistory.begin(); itHistory != rHistory.end(); itHistory++)
	{
		llReceivedBytes += (*itHistory).getReceivedBytes();
		llSentBytes += (*itHistory).getSentBytes();

		if( iPeriodCount >= uiPeriod )
		{
			pair< unsigned long, unsigned long > pairBytes(llReceivedBytes, llSentBytes);
			m_Graph.lstData.push_back(pairBytes);
			llReceivedBytes = llSentBytes = 0L;
			iPeriodCount = 0;
		}

		iPeriodCount++;
	}

	pair< unsigned long, unsigned long > pairBytes(llReceivedBytes, llSentBytes);
	m_Graph.lstData.push_back(pairBytes);

	strValue = pConfig->getValue("GraphScale");

	if(strValue == "Off")
		bScaleInfo = false;

	m_Graph.setScaleInfo(bScaleInfo);
	m_Graph.setPeriod(uiPeriod);

	strValue = pConfig->getValue("GraphSource");

	if(strValue == "In")
		m_Graph.Draw(rInterface.getWindow(), In);
	else if(strValue == "Out")
		m_Graph.Draw(rInterface.getWindow(), Out);
	else
		m_Graph.Draw(rInterface.getWindow(), InOut);

	rInterface.setDrawn(true);
}
