//------------------------------------------------------------------------------
//	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 XmlReport.cpp
 * @author Ronald Kluth
 * @date created at 2009/04/05
 * @brief Implementation of class odemx::data::output::XmlReport
 * @sa XmlReport.h
 * @since 3.0
 */

#include <odemx/data/output/XmlReport.h>
#include <odemx/data/buffer/StatisticsBuffer.h>
#include <odemx/util/Exceptions.h>
#include <odemx/util/StringConversion.h>
#include <odemx/resources/XmlReport_xsl.h>

#include <Poco/XML/XMLWriter.h>
#include <Poco/SAX/AttributesImpl.h>
#include <Poco/File.h>

#include <fstream>
#include <iostream>
#include <cstdlib> // we need abort if XmlReport.xsl can't be found

namespace odemx {
namespace data {
namespace output {

//------------------------------------------------------construction/destruction

XmlReport::XmlReport( const std::string& fileName )
:	fileStream_( fileName.c_str() )
,	xmlWriter_( 0 )
{
	if( ! fileStream_.good() )
	{
		throw DataOutputException( std::string( "XmlReport(): error opening file: " )
				+ fileName );
	}
}

XmlReport::~XmlReport()
{
}

//---------------------------------------------------------------xml file output

void copyXsl()
{
  /* Poco::File::copyTo throws an exception if the given file can't be found. 
   * If that happens, we have to abort the execution and tell the user about it. 
   * */
  try {
    std::ofstream stylesheet ("XmlReport.xsl", std::ios_base::out | std::ios_base::trunc );
    //Poco::File stylesheet( "XmlReport.xsl" );
    //stylesheet.createFile();
    stylesheet << resources::XmlReport_xsl::val;
  } catch (... ) {
    std::cerr << "Fatal error: XmlReport.xsl can't be found. Did you set ODEMX_HOME?" << std::endl;
    std::abort ();
  }
}

void XmlReport::startProcessing()
{
	copyXsl(); // to current working directory

	xmlWriter_.reset( new Poco::XML::XMLWriter( fileStream_,
			Poco::XML::XMLWriter::WRITE_XML_DECLARATION |
			Poco::XML::XMLWriter::PRETTY_PRINT ) );

	xmlWriter_->startDocument();

	// link the XSL stylesheet to the XML report
	xmlWriter_->processingInstruction( "xml-stylesheet",
			"type=\"text/xsl\" href=\"XmlReport.xsl\"" );

	xmlWriter_->startElement( "", "", "odemxreport" );
}

void XmlReport::endProcessing()
{
	xmlWriter_->endElement( "", "", "odemxreport" );
	xmlWriter_->endDocument();
	if( fileStream_.is_open() )
	{
		fileStream_.close();
	}
}

void XmlReport::processTables()
{
	if( tables_.empty() )
	{
		return;
	}

	Poco::XML::AttributesImpl attrs;

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

		if( ! table )
		{
			continue;
		}

		// start table
		attrs.clear();
		attrs.addAttribute( "","","label", "CDATA", table->getLabel() );
		attrs.addAttribute( "","","columns", "CDATA", toString( table->getNumberOfColumns() ) );
		attrs.addAttribute( "","","lines", "CDATA", toString( table->getNumberOfLines() ) );
		xmlWriter_->startElement( "", "", "table", attrs );

		// write column descriptions with label, number, and type
		for( ReportTable::SizeType col = 0; col < table->getNumberOfColumns(); ++col )
		{
			attrs.clear();
			attrs.addAttribute( "","","number", "CDATA", toString( col + 1 ) );
			attrs.addAttribute( "","","label", "CDATA", table->getLabelOfColumn( col ) );
			attrs.addAttribute( "","","type", "CDATA",
					ReportTable::Column::typeToString( table->getTypeOfColumn( col ) ) );
			xmlWriter_->startElement( "","","column", attrs );
			xmlWriter_->endElement( "","","column" );
		}

		// write cells to XML
		for( ReportTable::SizeType line = 0; line < table->getNumberOfLines(); ++line )
		{
			// start line
			attrs.clear();
			attrs.addAttribute( "","","number", "CDATA", toString( line + 1 ) );
			xmlWriter_->startElement( "","","line", attrs );

			for( ReportTable::SizeType col = 0; col < table->getNumberOfColumns(); ++col )
			{
				// write cell
				xmlWriter_->dataElement( "","","cell", table->getSTRING( col, line ),
						"col", toString( col + 1 ) );
			}
			// close line
			xmlWriter_->endElement( "","","line" );
		}
		// close table
		xmlWriter_->endElement( "", "", "table" );
	}
}

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