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

import java.util.ArrayList;
import java.util.List;

import org.eclipse.birt.data.engine.core.DataException;
import org.eclipse.birt.data.engine.executor.BaseQuery;
import org.eclipse.birt.data.engine.odi.IResultIterator;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;

/**
 * A registry of aggregate expressions. Stores all aggregate expressions that appears
 * in a report query or subquery
 */
public final class AggregateTable
{
	/** Array of AggrExprInfo objects to record all aggregates */
	private List aggrExprInfoList;
	
	/** */
	private List groupDefns;
	private Scriptable scope;
	
	/** the base query contains aggregate */
	private BaseQuery baseQuery;
		
	/**
	 * Used for de-serialization
	 */
	public AggregateTable( )
	{
		this.aggrExprInfoList = new ArrayList( );
	}

	/**
	 * construct the aggregateTable from preparedQuery
	 * 
	 * @param query
	 */
	public AggregateTable( Scriptable scope, List groupDefns )
	{
		this( );
		
		this.groupDefns = groupDefns;
		this.scope = scope;
	}

	/**
	 * construct the aggregateTable from baseQuery
	 * 
	 * @param query
	 */
	public AggregateTable( BaseQuery query )
	{
		this( );
		
		this.baseQuery = query;
	}
	
	//--------------registration of aggregation ------------------------------
	
	/**
	 * Returns an implementation of the AggregateRegistry interface used by
	 * ExpressionCompiler, to register aggregate expressions at the specified
	 * grouping level
	 * 
	 * @param groupLevel
	 * @param afterGroup
	 * @param cx
	 * @return
	 * @throws DataException 
	 */
	public AggregateRegistry getAggrRegistry( int groupLevel, int calculationLevel,
			boolean isDetailedRow, Context cx ) throws DataException
	{
		AggrRegistry aggrRegistry = new AggrRegistry( groupLevel,
				calculationLevel,
				isDetailedRow,
				cx );
		aggrRegistry.prepare( groupDefns, scope, baseQuery, aggrExprInfoList );
		return aggrRegistry;
	}

	//--------------calculation of aggregation ------------------------------
	
	private AggregateCalculator currentCalculator;

	/**
	 * @param odiResult
	 * @param scope
	 * @throws DataException
	 */
	public void calculate( IResultIterator odiResult, Scriptable scope )
			throws DataException
	{
		currentCalculator = new AggregateCalculator( aggrExprInfoList, odiResult );
		currentCalculator.calculate( scope );
	}
	
	/**
	 * @param odiResult
	 * @param scope
	 * @param aggrValue
	 * @throws DataException
	 */
	public void calculate( IResultIterator odiResult, Scriptable scope,
			JSAggrValueObject aggrValue )
			throws DataException
	{
		currentCalculator = new AggregateCalculator( aggrExprInfoList, odiResult );
		currentCalculator.calculate( scope );
	}
	
	/**
	 * @return
	 */
	public Scriptable getJSAggrValueObject( )
	{
		if ( currentCalculator == null )
			return null;

		return currentCalculator.getJSAggrValueObject( );
	}
	
}