
package org.eclipse.birt.report.engine.api.document;

import java.io.ByteArrayOutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.report.engine.EngineCase;
import org.eclipse.birt.report.engine.api.HTMLRenderOption;
import org.eclipse.birt.report.engine.api.IDataExtractionTask;
import org.eclipse.birt.report.engine.api.IDataIterator;
import org.eclipse.birt.report.engine.api.IExtractionResults;
import org.eclipse.birt.report.engine.api.IRenderOption;
import org.eclipse.birt.report.engine.api.IRenderTask;
import org.eclipse.birt.report.engine.api.IReportDocument;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IResultMetaData;
import org.eclipse.birt.report.engine.api.InstanceID;
import org.eclipse.birt.report.model.api.DesignElementHandle;
import org.eclipse.birt.report.model.api.ListHandle;
import org.eclipse.birt.report.model.api.ReportDesignHandle;
import org.eclipse.birt.report.model.api.TableHandle;

/**
 * in the report document, we have:
 * 
 * table id="6" bookmark is reportlet_table list id="38" bookmark is
 * reportlet_group_[groupid]
 * 
 * 
 * @author yanwei
 * 
 */
public class ReportDocumentTest extends EngineCase
{

	final String REPORT_DOCUMENT = "./utest/report.rptdocument";
	final String REPORT_DOCUMENT_V2_1_0 = "org/eclipse/birt/report/engine/api/document/v2_1_0.rptdocument";

	public void tearDown( )
	{
		removeFile( REPORT_DOCUMENT );
	}

	public void testV2_1_0( ) throws Exception
	{
		copyResource( REPORT_DOCUMENT_V2_1_0, REPORT_DOCUMENT );
		doTestDocument( );
		super.removeFile( REPORT_DOCUMENT );

	}

	void doTestDocument( ) throws Exception
	{
		doRenderPages( );
		doRenderAll( );
		doRenderReportletWithInstanceID( );
		doRenderReportletWithBookmark( );
		doDataExtractionWithInstanceID( );
	}

	void doRenderPages( ) throws Exception
	{
		IReportDocument document = engine.openReportDocument( REPORT_DOCUMENT );
		long totalPage = document.getPageCount( );
		assertEquals( 2, totalPage );
		ByteArrayOutputStream out = new ByteArrayOutputStream( );
		for ( long pageNumber = 1; pageNumber <= totalPage; pageNumber++ )
		{
			IRenderTask renderTask = engine.createRenderTask( document );
			IRenderOption option = new HTMLRenderOption( );
			option.setOutputFormat( HTMLRenderOption.OUTPUT_FORMAT_HTML );
			option.setOutputStream( out );
			renderTask.setRenderOption( option );
			renderTask.setPageNumber( pageNumber );
			renderTask.render( );
			assertTrue( renderTask.getErrors( ).isEmpty( ) );
			renderTask.close( );
			String pageContent = out.toString( "UTF-8" );
			if ( pageNumber == 1 )
			{
				assertTrue( pageContent.indexOf( "reportlet_table" ) != -1 );
				assertTrue( pageContent.indexOf( "SECOND-PAGE" ) == -1 );
			}
			else
			{
				assertTrue( pageContent.indexOf( "reportlet_table" ) == -1 );
				assertTrue( pageContent.indexOf( "SECOND-PAGE" ) != -1 );
			}
			out.reset( );
		}
		document.close( );
	}

	void doRenderAll( ) throws Exception
	{
		IReportDocument document = engine.openReportDocument( REPORT_DOCUMENT );
		ByteArrayOutputStream out = new ByteArrayOutputStream( );
		IRenderTask renderTask = engine.createRenderTask( document );
		IRenderOption option = new HTMLRenderOption( );
		option.setOutputFormat( HTMLRenderOption.OUTPUT_FORMAT_HTML );
		option.setOutputStream( out );
		renderTask.setRenderOption( option );
		renderTask.render( );
		assertTrue( renderTask.getErrors( ).isEmpty( ) );
		renderTask.close( );
		String pageContent = out.toString( "UTF-8" );
		assertTrue( pageContent.indexOf( "reportlet_table" ) != -1 );
		assertTrue( pageContent.indexOf( "SECOND-PAGE" ) != -1 );
		document.close( );
	}

	void doRenderReportletWithInstanceID( ) throws Exception
	{
		IReportDocument document = engine.openReportDocument( REPORT_DOCUMENT );
		ByteArrayOutputStream out = new ByteArrayOutputStream( );
		IRenderTask renderTask = engine.createRenderTask( document );
		IRenderOption option = new HTMLRenderOption( );
		option.setOutputFormat( HTMLRenderOption.OUTPUT_FORMAT_HTML );
		option.setOutputStream( out );
		renderTask.setRenderOption( option );
		renderTask.render( );
		renderTask.close( );
		String content = out.toString( "UTF-8" );
		out.reset( );

		Pattern iidPattern = Pattern.compile( "iid=\"([^\"]*)\"" );
		Matcher matcher = iidPattern.matcher( content );
		while ( matcher.find( ) )
		{
			String strIid = matcher.group( 1 );
			InstanceID iid = InstanceID.parse( strIid );
			long designId = iid.getComponentID( );
			IReportRunnable runnable = renderTask.getReportRunnable( );
			ReportDesignHandle report = (ReportDesignHandle) runnable
					.getDesignHandle( );
			DesignElementHandle element = report.getElementByID( designId );
			if ( element instanceof TableHandle
					|| element instanceof ListHandle )
			{
				renderTask = engine.createRenderTask( document );
				renderTask.setRenderOption( option );
				renderTask.setInstanceID( strIid );
				renderTask.render( );
				assertTrue( renderTask.getErrors( ).isEmpty( ) );
				renderTask.close( );
				String pageContent = out.toString( "UTF-8" );
				if ( element instanceof TableHandle )
				{
					// it cotains the table and all three lists
					assertTrue( pageContent.indexOf( "reportlet_table" ) != -1 );
					int indexOf = pageContent.indexOf( "reportlet_group" );
					int lastIndexOf = pageContent
							.lastIndexOf( "reportlet_group" );
					assertTrue( indexOf != -1 && lastIndexOf != -1
							&& indexOf != lastIndexOf );
				}
				else
				{
					// it contains the table and the single list
					assertTrue( pageContent.indexOf( "reportlet_table" ) != -1 );
					int indexOf = pageContent.indexOf( "reportlet_group" );
					int lastIndexOf = pageContent
							.lastIndexOf( "reportlet_group" );
					assertTrue( indexOf != -1 && lastIndexOf != -1
							&& indexOf == lastIndexOf );
				}
				out.reset( );
			}
		}
		document.close( );
	}

	void doRenderReportletWithBookmark( ) throws Exception
	{
		IReportDocument document = engine.openReportDocument( REPORT_DOCUMENT );
		ByteArrayOutputStream out = new ByteArrayOutputStream( );
		IRenderOption option = new HTMLRenderOption( );
		option.setOutputFormat( HTMLRenderOption.OUTPUT_FORMAT_HTML );
		option.setOutputStream( out );

		String[] bookmarks = new String[]{"reportlet_table",
				"reportlet_group_0", "reportlet_group_1", "reportlet_group_2"};

		for ( int i = 0; i < bookmarks.length; i++ )
		{
			IRenderTask renderTask = engine.createRenderTask( document );
			renderTask.setRenderOption( option );
			renderTask.setReportlet( bookmarks[i] );
			renderTask.render( );
			assertTrue( renderTask.getErrors( ).isEmpty( ) );
			renderTask.close( );
			String pageContent = out.toString( "UTF-8" );
			if ( bookmarks[i].indexOf( "group" ) == -1 )
			{
				// it cotains the table and all three lists
				assertTrue( pageContent.indexOf( "reportlet_table" ) != -1 );
				int indexOf = pageContent.indexOf( "reportlet_group" );
				int lastIndexOf = pageContent.lastIndexOf( "reportlet_group" );
				assertTrue( indexOf != -1 && lastIndexOf != -1
						&& indexOf != lastIndexOf );
			}
			else
			{
				// it contains the table and the single list
				assertTrue( pageContent.indexOf( "reportlet_table" ) != -1 );
				int indexOf = pageContent.indexOf( "reportlet_group" );
				int lastIndexOf = pageContent.lastIndexOf( "reportlet_group" );
				assertTrue( indexOf != -1 && lastIndexOf != -1
						&& indexOf == lastIndexOf );
			}
			out.reset( );
		}
		document.close( );

	}

	void doDataExtractionWithInstanceID( ) throws Exception
	{
		IReportDocument document = engine.openReportDocument( REPORT_DOCUMENT );
		ByteArrayOutputStream out = new ByteArrayOutputStream( );
		IRenderTask renderTask = engine.createRenderTask( document );
		IRenderOption option = new HTMLRenderOption( );
		option.setOutputFormat( HTMLRenderOption.OUTPUT_FORMAT_HTML );
		option.setOutputStream( out );
		renderTask.setRenderOption( option );
		renderTask.render( );
		renderTask.close( );
		String content = out.toString( "UTF-8" );

		Pattern iidPattern = Pattern.compile( "iid=\"([^\"]*)\"" );
		Matcher matcher = iidPattern.matcher( content );
		while ( matcher.find( ) )
		{
			String strIid = matcher.group( 1 );
			InstanceID iid = InstanceID.parse( strIid );
			long designId = iid.getComponentID( );
			IReportRunnable runnable = renderTask.getReportRunnable( );
			ReportDesignHandle report = (ReportDesignHandle) runnable
					.getDesignHandle( );
			DesignElementHandle element = report.getElementByID( designId );
			if ( element instanceof TableHandle
					|| element instanceof ListHandle )
			{
				IDataExtractionTask task = engine
						.createDataExtractionTask( document );
				task.setInstanceID( iid );
				IExtractionResults results = task.extract( );
				if ( element instanceof TableHandle )
				{
					assertEquals( 27, getFieldCount( results ) );
				}
				else
				{
					assertEquals( 6, getFieldCount( results ) );
				}
				task.close( );

			}
		}
		document.close( );
	}

	int getFieldCount( IExtractionResults results ) throws BirtException
	{
		int fieldCount = 0;
		IDataIterator iter = results.nextResultIterator( );
		IResultMetaData metaData = iter.getResultMetaData( );
		int columnCount = metaData.getColumnCount( );
		while ( iter.next( ) )
		{
			fieldCount += columnCount;
		}
		return fieldCount;
	}
}
