/*******************************************************************************
 * Copyright (c) 2004 Actuate Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *  Actuate Corporation  - initial API and implementation
 *******************************************************************************/

package org.eclipse.birt.data.engine.impl.document;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.eclipse.birt.core.util.IOUtil;
import org.eclipse.birt.data.engine.core.DataException;
import org.eclipse.birt.data.engine.i18n.ResourceConstants;

/**
 * Save util class
 */
public class RowSaveUtil
{
	private int lastRowIndex;
	private int currentOffset;

	private int rowCount;
	
	//
	private DataOutputStream rowExprsDos;
	private DataOutputStream rowLenDos;

	private boolean inited;

	private Set exprNameSet;

	/**
	 * 
	 */
	public RowSaveUtil( int rowCount, OutputStream rowExprsOs,
			OutputStream rowLenOs, Set exprNameSet )
	{
		this.rowCount = rowCount;
		this.exprNameSet = exprNameSet;
		
		this.rowExprsDos = new DataOutputStream( rowExprsOs );
		this.rowLenDos = new DataOutputStream( rowLenOs );
	}

	/**
	 * @param currIndex
	 * @param valueMap
	 * @throws DataException
	 */
	public void saveExprValue( int currIndex, Map valueMap )
			throws DataException
	{
		try
		{
			saveNullRowsBetween( lastRowIndex, currIndex );
			
			int rowBytes = saveExprValue( valueMap );
			IOUtil.writeInt( this.rowLenDos, currentOffset );
			currentOffset += rowBytes;

			lastRowIndex = currIndex;
		}
		catch ( IOException e )
		{
			throw new DataException( ResourceConstants.RD_SAVE_ERROR,
					e,
					"Result Data" );
		}
	}
	
	/**
	 * @param currIndex
	 * @param exprID
	 * @param exprValue
	 * @throws DataException
	 */
	public int saveExprValue( Map valueMap ) throws DataException
	{
		initSave( false );

		ByteArrayOutputStream tempBaos = new ByteArrayOutputStream( );
		BufferedOutputStream tempBos = new BufferedOutputStream( tempBaos );
		DataOutputStream tempDos = new DataOutputStream( tempBos );

		try
		{
			IOUtil.writeInt( tempDos, valueMap.size( ) );
			Iterator it = valueMap.entrySet( ).iterator( );
			while ( it.hasNext( ) )
			{
				Map.Entry entry = (Entry) it.next( );
				String exprID = (String) entry.getKey( );
				Object value = entry.getValue( );
				IOUtil.writeString( tempDos, exprID );
				IOUtil.writeObject( tempDos, value );
				exprNameSet.add( exprID );
			}

			tempDos.flush( );
			tempBos.flush( );
			tempBaos.flush( );

			byte[] bytes = tempBaos.toByteArray( );
			int rowBytes = bytes.length;
			IOUtil.writeRawBytes( this.rowExprsDos, bytes );

			tempBaos = null;
			tempBos = null;
			tempDos = null;
			
			return rowBytes;
		}
		catch ( IOException e )
		{
			throw new DataException( ResourceConstants.RD_SAVE_ERROR,
					e,
					"Result Data" );
		}
	}

	/**
	 * @param currIndex
	 * @throws DataException
	 */
	public void saveFinish( int currIndex ) throws DataException
	{
		initSave( true );

		try
		{
			saveNullRowsBetween( lastRowIndex, currIndex );

			rowExprsDos.close( );
			rowLenDos.close( );
		}
		catch ( IOException e )
		{
			throw new DataException( ResourceConstants.RD_SAVE_ERROR,
					e,
					"Result Data" );
		}
	}

	/**
	 * init save environment
	 */
	private void initSave( boolean finish ) throws DataException
	{
		if ( inited == true )
			return;

		inited = true;
		try
		{
			int totalRowCount = 0;
			if ( finish == true )
				totalRowCount = rowCount;
			else
				totalRowCount = rowCount == 0 ? 1 : rowCount;

			// TODO: enhance me
			IOUtil.writeInt( this.rowExprsDos, totalRowCount );
		}
		catch ( IOException e )
		{
			throw new DataException( ResourceConstants.RD_SAVE_ERROR, e );
		}
	}
	
	/**
	 * @param lastRowIndex
	 * @param currIndex
	 * @throws IOException
	 */
	private void saveNullRowsBetween( int lastRowIndex, int currIndex )
			throws IOException
	{
		int gapRows = currIndex - lastRowIndex - 1;
		for ( int i = 0; i < gapRows; i++ )
		{
			IOUtil.writeInt( this.rowExprsDos, 0 );
			IOUtil.writeInt( this.rowLenDos, currentOffset );
			currentOffset += IOUtil.INT_LENGTH;
		}
	}
	
}

@@ -1567,16 +1567,42 @@
 enOs );%0A
+%09%09this.lastRowIndex = -1;%0A
 %09%7D%0A%0A%09/**
@@ -1761,32 +1761,58 @@
 on%0A%09%7B%0A%09%09try%0A%09%09%7B%0A
+%09%09%09initSave( false );%0A%09%09%09%0A
 %09%09%09saveNullRowsB
@@ -2240,21 +2240,22 @@
 %0A%09 */%0A%09p
-ublic
+rivate
  int sav
@@ -2309,30 +2309,8 @@
 %0A%09%7B%0A
-%09%09initSave( false );%0A%0A
 %09%09By

Fix bug 148503: [regression] Data in list footer cannot be previewed in Web viewer