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

import org.eclipse.birt.test.performance.parser.TestCaseNode;

/**
 * Execution - provide entry point to this test suite
 */
public class CaseRunner
{

	private TestCaseNode testcase = null;
	private Semaphore semaphore = null;

	/**
	 * Constructor for a new CaseRunner.
	 * 
	 * @param testcase
	 * @param caseSemaphore
	 */
	public CaseRunner( TestCaseNode testcase )
	{
		this.testcase = testcase;
		this.semaphore = new Semaphore( 0 );
	}

	/**
	 * Run a test case, one case contains multiple tasks: run, render(All),
	 * renderN, runAndRender
	 */

	public void run( )
	{
		ExecutionContext context = new ExecutionContext( );

		// warmup the engine.
		System.out.println( "Warming up for: " + testcase.getName( ) ); //$NON-NLS-1$
		warmup( context );
		System.out.println( "End warming up(" + testcase.getName( ) + ")" ); //$NON-NLS-1$ //$NON-NLS-2$
		System.out.println( "\n" ); //$NON-NLS-1$

		context.setTestcase( testcase );

		String[] tasks = testcase.getTasks( );
		for ( int index = 0; index < tasks.length; index++ )
		{
			String task = tasks[index].trim( );
			if ( task.equalsIgnoreCase( "run" ) )
				executeTask( Constants.TASK_RUN_ID, context );
			else if ( task.equalsIgnoreCase( "renderAll" ) )
				executeTask( Constants.TASK_RENDER_ALL_ID, context );
			else if ( task.equalsIgnoreCase( "renderN" ) )
				executeTask( Constants.TASK_RENDER_N_ID, context );
			else
				/* it should be runandrender task */
				executeTask( Constants.TASK_RUN_AND_RENDER_ID, context );
		}
	}

	private void executeTask( int taskid, ExecutionContext context )
	{
		TestCaseNode testcase = context.getTestcase( );
		int threadCount = testcase.getThreads( );

		System.out.println( "Start testcase[" + testcase.getName( ) + "] task[" + Constants.TASK_NAMES[taskid] + "]" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

		Thread thread = null;
		for ( int i = 0; i < threadCount; i++ )
		{
			this.semaphore.acquire( );

			switch ( taskid )
			{
				case Constants.TASK_RUN_ID :
					thread = new RunThread( Constants.TASK_RUN,
							i,
							context,
							semaphore );
					break;

				case Constants.TASK_RENDER_ALL_ID :
					thread = new RenderThread( Constants.TASK_RENDER_ALL,
							i,
							context,
							semaphore,
							0 );
					break;

				case Constants.TASK_RENDER_N_ID :
					thread = new RenderThread( Constants.TASK_RENDER_N,
							i,
							context,
							semaphore,
							1 );
					break;

				case Constants.TASK_RUN_AND_RENDER_ID :
					thread = new RunRenderThread( Constants.TASK_RUN_AND_RENDER,
							i,
							context,
							semaphore );
					break;
			}

			thread.start( );
		}

		// waiting for the threads to complete.

		this.semaphore.holdup( );
		this.semaphore.reset( );

		System.out.println( "Complete testcase[" + testcase.getName( ) + "] task[" + Constants.TASK_NAMES[taskid] + "]" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	/**
	 * Warmup the engine by run/render/runrender a report.
	 * 
	 * @param context
	 */

	private void warmup( ExecutionContext context )
	{
		TestCaseNode warmupCase = new TestCaseNode( );
		warmupCase.setName( "case-warmup" ); //$NON-NLS-1$
		warmupCase.setEncoding( "UTF-8" ); //$NON-NLS-1$
		warmupCase.setFormat( "pdf" ); //$NON-NLS-1$
		warmupCase.setLocale( "EN_US" ); //$NON-NLS-1$
		warmupCase.setThreads( 1 );
		warmupCase.setReport( "21" ); //$NON-NLS-1$
		warmupCase.build( );

		context.setTestcase( warmupCase );

		executeTask( Constants.TASK_RUN_ID, context );
		executeTask( Constants.TASK_RENDER_ALL_ID, context );
		executeTask( Constants.TASK_RUN_AND_RENDER_ID, context );

	}

}