/*******************************************************************************
 * 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.viewing;

import org.eclipse.birt.data.engine.core.DataException;
import org.eclipse.birt.data.engine.executor.cache.CacheRequest;
import org.eclipse.birt.data.engine.executor.cache.OdiAdapter;
import org.eclipse.birt.data.engine.executor.cache.ResultSetCache;
import org.eclipse.birt.data.engine.executor.cache.SmartCache;
import org.eclipse.birt.data.engine.executor.cache.SortSpec;
import org.eclipse.birt.data.engine.impl.DataEngineSession;
import org.eclipse.birt.data.engine.impl.document.util.IExprDataResultSet;
import org.eclipse.birt.data.engine.odi.IResultClass;
import org.eclipse.birt.data.engine.odi.IResultObject;

/**
 * This result set will do group sorting.
 */
public class ExprTotalDataResultSet implements IExprDataResultSet
{
	private ResultSetCache initRsCache;
	
	private ResultSetCache currRsCache;
	private IResultClass resultClass;
	private int[] groupRowIndex;
	private int rowCount;
	private SortSpec sortSpec;
	
	private int rowIndex;
	
	private int[] endIndexInGroup;
	private int[] rowCountInGroup;
	private int groupIndex;
	
	private DataEngineSession session;
	/**
	 * @param rsCache, the source of data
	 * @param resultClass
	 * @param sortSpec
	 * @param groupRowIndex
	 * @param count
	 */
	public ExprTotalDataResultSet( ResultSetCache rsCache,
			IResultClass resultClass, SortSpec sortSpec, int[] groupRowIndex,
			int count, DataEngineSession session )
	{
		this.initRsCache = rsCache;
		this.sortSpec = sortSpec;
		this.resultClass = resultClass;
		this.groupRowIndex = groupRowIndex;
		this.rowCount = count;
		this.session = session;
		this.prepare( );
	}
	
	/**
	 *
	 */
	private void prepare()
	{
		int groupCount = groupRowIndex.length / 2;
		
		this.endIndexInGroup = new int[groupCount];
		this.rowCountInGroup = new int[groupCount];

		for ( int i = 0; i < groupCount; i++ )
		{
			int startIndex = groupRowIndex[2 * i];
			int endIndex = groupRowIndex[2 * i + 1];
			endIndexInGroup[i] = endIndex;
			rowCountInGroup[i] = endIndex - startIndex;
		}
	}
	
	/*
	 * @see org.eclipse.birt.data.engine.odi.IExprDataResultSet#getResultClass()
	 */
	public IResultClass getResultClass( )
	{
		return resultClass;
	}

	/*
	 * @see org.eclipse.birt.data.engine.odi.IExprDataResultSet#fetch()
	 */
	public IResultObject next( ) throws DataException
	{
		return this.fetch( );
	}
	
	/*
	 * @see org.eclipse.birt.data.engine.odi.IExprDataResultSet#fetch()
	 */
	public IResultObject fetch( ) throws DataException
	{
		if ( rowIndex == rowCount )
		{
			if ( currRsCache != null )
			{
				currRsCache.close( );
				currRsCache = null;
			}
			return null;
		}
		
		if ( rowIndex == endIndexInGroup[groupIndex] )
		{
			groupIndex++;
			currRsCache.close( );
			currRsCache = null;
		}

		if ( currRsCache == null )
		{
			ExprGroupDataResultSet groupExprResultSet = new ExprGroupDataResultSet( initRsCache,
					resultClass,
					rowCountInGroup[groupIndex] );

			currRsCache = new SmartCache( new CacheRequest( 0,
					null,
					sortSpec,
					new DummyEventHandler( ) ),
					new OdiAdapter( groupExprResultSet ),
					this.resultClass, this.session );
		}

		rowIndex++;
		IResultObject ro = currRsCache.fetch( );
		return ro;
	}
	
	/*
	 * @see org.eclipse.birt.data.engine.odi.IExprDataResultSet#getCount()
	 */
	public int getCount( ) throws DataException
	{
		return rowCount;
	}
	
	/*
	 * @see org.eclipse.birt.data.engine.impl.document.viewing.IExprDataResultSet#getRealCount()
	 */
	public int getRealCount( ) throws DataException
	{
		return rowCount;
	}

	/*
	 * @see org.eclipse.birt.data.engine.impl.document.viewing.IExprDataResultSet#close()
	 */
	public void close( )
	{
		if ( initRsCache != null )
			initRsCache.close( );
		if ( currRsCache != null )
			this.currRsCache.close( );
	}

}
