/*******************************************************************************
 * 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.tests.data.engine.regression;

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

import org.eclipse.birt.core.data.DataType;
import org.eclipse.birt.data.engine.api.IPreparedQuery;
import org.eclipse.birt.data.engine.api.IQueryResults;
import org.eclipse.birt.data.engine.api.IResultIterator;
import org.eclipse.birt.data.engine.api.IScriptExpression;
import org.eclipse.birt.data.engine.api.querydefn.ColumnDefinition;
import org.eclipse.birt.data.engine.api.querydefn.QueryDefinition;
import org.eclipse.birt.data.engine.api.querydefn.ScriptDataSetDesign;
import org.eclipse.birt.data.engine.api.querydefn.ScriptDataSourceDesign;
import org.eclipse.birt.data.engine.api.querydefn.ScriptExpression;

import testutil.APITestCase;

/**
 * <b>Bug description</b>
 * <p>
 * Setting an alias on a column belonging to the scripted datasource will get an
 * error
 * <p>
 * <b>Test description</b>
 * <p>
 * Create a scripted data and set several Alias on it.
 * <P>
 * 1. Confirm the Alias name is set
 * <P>
 * 2. Compare the result which referenced by Alias with the golden.
 */

public class Regression_137149 extends APITestCase
{

	// data set name
	private final String dataSetName = "ScriptedDataSet";

	// test features
	private final static int TEST_NONE = 0;
	private final static int TEST_SORT = 1;
	private final static int TEST_GROUP = 2;
	private final static int TEST_MAXROW = 3;
	private final static int TEST_TOPN_FILTER = 4;

	// column name
	private String[] scriptColumnNames = new String[]{"NUM", "SQUARE", "STR",
			"ANY"};
	private int[] scriptColumnTypes = new int[]{DataType.INTEGER_TYPE,
			DataType.DOUBLE_TYPE, DataType.STRING_TYPE, DataType.ANY_TYPE};

	// column alias name
	private String[] scriptColumnAliasNames = new String[]{"NUM2", "SQUARE2",
			"STR2", "ANY2"};

	private IScriptExpression[] scriptExprs;

	private IScriptExpression[] aliasScriptExprs;

	private ScriptDataSourceDesign dsource;

	private ScriptDataSetDesign dset;

	/*
	 * @see org.eclipse.birt.data.engine.api.APITestCase#getDataSourceInfo()
	 */
	protected DataSourceInfo getDataSourceInfo( )
	{
		return null;
	}

	/**
	 * @param dynamicMetadata
	 * @throws Exception
	 */
	private void init( ) throws Exception
	{
		// Create script data set and data source
		dsource = new ScriptDataSourceDesign( "JUST as place folder" );
		dset = newDataSet( null );
		dset.setDataSource( dsource.getName( ) );

		dataEngine.defineDataSource( dsource );
		dataEngine.defineDataSet( dset );

		// Generate script expressions
		scriptExprs = new IScriptExpression[]{
				new ScriptExpression( "dataSetRow." + scriptColumnNames[0] ),
				new ScriptExpression( "dataSetRow." + scriptColumnNames[1] ),
				new ScriptExpression( "dataSetRow." + scriptColumnNames[2] ),
				new ScriptExpression( "dataSetRow." + scriptColumnNames[3] )};

		aliasScriptExprs = new IScriptExpression[]{
				new ScriptExpression( "dataSetRow." + scriptColumnAliasNames[0] ),
				new ScriptExpression( "dataSetRow." + scriptColumnAliasNames[1] ),
				new ScriptExpression( "dataSetRow." + scriptColumnAliasNames[2] ),
				new ScriptExpression( "dataSetRow." + scriptColumnAliasNames[3] )};
	}

	private ScriptDataSetDesign newDataSet( String name )
	{
		ScriptDataSetDesign dataSet = new ScriptDataSetDesign( name == null
				? dataSetName
				: name );

		// 1: add scripts
		dataSet.setOpenScript( "count=10;" );

		dataSet
				.setFetchScript( "if (count==0) {return false; } else "
						+ "{ row.NUM=count; row.SQUARE=count*count; row.STR=\"row#\" + count; "
						+ " row[4]=count<5; " + "--count; return true; }" );

		// 2: add column hints - only in the case of static metadata

		boolean addAll = dataSet.getResultSetHints( )
				.addAll( getColumnHints( ) );

		return dataSet;
	}

	private List getColumnHints( )
	{
		ArrayList list = new ArrayList( );
		for ( int i = 0; i < scriptColumnNames.length; i++ )
		{
			ColumnDefinition col = new ColumnDefinition( scriptColumnNames[i] );
			col.setDataType( scriptColumnTypes[i] );
			col.setAlias( scriptColumnAliasNames[i] );
			list.add( col );
		};
		return list;
	}

	/**
	 * Test fetch with alias
	 * 
	 * @throws Exception
	 */
	public void testGetScriptedDatasetAlias( ) throws Exception
	{
		init( );
		// IQueryDefinition rqDefn = getReportQueryDefn( TEST_GROUP );
		QueryDefinition rqDefn = new QueryDefinition( );
		// add expressions

		rqDefn.setDataSetName( dataSetName );
		for ( int i = 0; i < this.scriptExprs.length; i++ )
		{
			rqDefn.addResultSetExpression( "_" + scriptColumnNames[i],
					scriptExprs[i] );
		}
		for ( int i = 0; i < this.aliasScriptExprs.length; i++ )
		{
			rqDefn.addResultSetExpression( "_" + scriptColumnAliasNames[i],
					aliasScriptExprs[i] );
		}

		IPreparedQuery pq = dataEngine.prepare( rqDefn );
		IQueryResults qr = pq.execute( jsScope );
		IResultIterator ri = qr.getResultIterator( );

		for ( int i = 1; i < 4; i++ )
		{
			assertEquals( scriptColumnAliasNames[i - 1], ri.getResultMetaData( )
					.getColumnAlias( i ) );
		}

		int rowIndex = 0;

		while ( ri.next( ) )
		{
			String outputStr = "";
			for ( int i = 0; i < this.scriptColumnAliasNames.length; i++ )
			{
				Object value = ri.getValue( "_" + scriptColumnAliasNames[i] );
				outputStr += aliasScriptExprs[i].getText( ).replaceAll(
						"dataSetRow", "row" )
						+ " value is:" + value.toString( ) + "    ";
			}

			rowIndex++;
			testPrintln( outputStr );
		}

		ri.close( );
		qr.close( );

		// Shutdown data engine to close all data sources; this ensures that
		// the script data source's close event scripts will run
		dataEngine.shutdown( );
		checkOutputFile( );
	}

}
