//------------------------------------------------------------------------------
//	Copyright (C) 2009, 2010 Humboldt-Universitaet zu Berlin
//
//	This library is free software; you can redistribute it and/or
//	modify it under the terms of the GNU Lesser General Public
//	License as published by the Free Software Foundation; either
//	version 2.1 of the License, or (at your option) any later version.
//
//	This library 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
//	Lesser General Public License for more details.
//
//	You should have received a copy of the GNU Lesser General Public
//	License along with this library; if not, write to the Free Software
//	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/**
 * @file OStreamReport.cpp
 * @author Ronald Kluth
 * @date created at 2009/02/28
 * @brief Implementation of class odemx::data::output::OStreamReport
 * @sa OStreamReport.h
 * @since 3.0
 */

#include <odemx/data/output/OStreamReport.h>
#include <odemx/data/buffer/StatisticsBuffer.h>

#include <iomanip>

namespace odemx {
namespace data {
namespace output {

OStreamReport::OStreamReport( std::ostream& os )
:	os_( os )
{
}

OStreamReport::~OStreamReport()
{
}

void OStreamReport::startProcessing()
{
	os_ << "ODEMx Statistics Report\n"
		<< "=======================";
}

void OStreamReport::endProcessing()
{
}

void OStreamReport::processTables()
{
	using namespace std;

	if( tables_.empty() )
	{
		os_ << "\n\n" << "no statistics tables to display\n";
		return;
	}

	// write tables
	for( TableVec::const_iterator iter = tables_.begin();
		iter != tables_.end(); ++iter )
	{
		ReportTable* table = *iter;

		if( ! table )
		{
			continue;
		}

		// title
		os_ << "\n\n" << table->getLabel() << "\n";
		os_ << string( table->getLabel().length(), '-' ) << "\n";
		os_ << left;

		// compute column widths
		std::deque< std::size_t > colWidths( table->getNumberOfColumns(), 0 );

		for( ReportTable::SizeType col = 0; col < table->getNumberOfColumns(); ++col )
		{
			for( ReportTable::SizeType line = 0; line < table->getNumberOfLines(); ++line )
			{
				std::size_t currentWidth = 0;
				switch( table->getTypeOfColumn( col ) )
				{
				case ReportTable::Column::REAL: // fall through
				case ReportTable::Column::STRING:
				case ReportTable::Column::INTEGER:
				case ReportTable::Column::SIMTIME:
					currentWidth = table->getSTRING( col, line ).size();
					break;
				case ReportTable::Column::BAR:
				{
					long barSize = table->getBAR( col, line );
					if( barSize < 0 )
					{
						currentWidth = 0;
					}
					else
					{
						currentWidth = barSize;
					}
					break;
				}
				default:
					break;
				}
				// store max value
				colWidths[ col ] = std::max( colWidths[ col ], currentWidth );
				colWidths[ col ] = std::max( colWidths[ col ], table->getLabelOfColumn( col ).size() );
			}

		}

		// write column labels
		for( ReportTable::SizeType i = 0; i < table->getNumberOfColumns(); ++i )
		{
			os_ << setw( colWidths[ i ] )
				<< table->getLabelOfColumn( i )
				<< " | ";
		}

		// write lines
		for( ReportTable::SizeType line = 0; line < table->getNumberOfLines(); ++line )
		{
			os_ << "\n";

			// write cells
			for( ReportTable::SizeType col = 0; col < table->getNumberOfColumns(); ++col )
			{
				switch( table->getTypeOfColumn( col ) )
				{
				case ReportTable::Column::REAL: // fall through
				case ReportTable::Column::STRING:
				case ReportTable::Column::INTEGER:
				case ReportTable::Column::SIMTIME:
					os_ << setw( colWidths[ col ] )
						<< table->getSTRING( col, line )
						<< " | ";
					break;
				case ReportTable::Column::BAR:
				{
					long barSize = table->getBAR( col, line );
					if( barSize > 0 )
					{
						os_ << left << string( table->getBAR( col, line ), '*' );
					}
					break;
				}
				default:
					break;
				}
			}
		}
	}
	os_ << "\n" << endl;
}

} } } // namespace odemx::data::output
