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

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.crimson.tree.ElementNode;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 
 * 
 */

public class ConfigurationReader implements ISchemaConstants
{

	private static Configuration instance = Configuration.getInstance( );

	/**
	 * Read an config file given as a stream.
	 * 
	 * @param is
	 * @throws Exception
	 */
	public static void parse( InputStream is ) throws Exception
	{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance( );
		DocumentBuilder builder = factory.newDocumentBuilder( );
		Document document = builder.parse( is );

		NodeList root = document.getElementsByTagName( TEST_SUITE_TAG );

		if ( null == root || root.getLength( ) == 0 )
		{
			System.err.println( "No testsuite tag." ); //$NON-NLS-1$
			return;
		}

		// there will be only one TestSuite element
		Element testsuite = (Element) root.item( 0 );
		instance.setSuiteName( testsuite.getAttributes( )
				.getNamedItem( NAME_ATTR )
				.getNodeValue( ) );

		NodeList input = testsuite.getElementsByTagName( INPUT_TAG );
		NodeList testcases = testsuite.getElementsByTagName( TEST_CASE_TAG );

		if ( null == input || input.getLength( ) == 0 )
		{
			System.err.println( "No input reports included." ); //$NON-NLS-1$
			return;
		}

		if ( null == testcases || testcases.getLength( ) == 0 )
		{
			System.err.println( "No testcase included." ); //$NON-NLS-1$
			return;
		}

		NodeList reportdesingTags = ( (ElementNode) input.item( 0 ) ).getElementsByTagName( REPORT_DESIGN_TAG );
		for ( int i = 0; i < reportdesingTags.getLength( ); i++ )
		{
			Node reportdesign = reportdesingTags.item( i );
			String id = reportdesign.getAttributes( )
					.getNamedItem( ID_ATTR )
					.getNodeValue( );
			String name = reportdesign.getAttributes( )
					.getNamedItem( NAME_ATTR )
					.getNodeValue( );
			String docType = reportdesign.getAttributes( )
					.getNamedItem( DOC_TYPE_ATTR )
					.getNodeValue( );
			String pageN = reportdesign.getAttributes( )
					.getNamedItem( PAGE_N_ATTR )
					.getNodeValue( );
			String repeat = reportdesign.getAttributes( )
					.getNamedItem( REPEAT_ATTR )
					.getNodeValue( );

			ReportDesignNode report = new ReportDesignNode( );
			report.id = id;
			report.name = name;
			report.docType = docType;
			report.pageN = Integer.parseInt( pageN );
			report.repeat = Integer.parseInt( repeat );
			
			if ( !report.docType.equalsIgnoreCase( "file" ) )
				if ( !report.docType.equalsIgnoreCase( "folder" ) )
				{
					System.err.println( "invalid docType: " + report.docType );
					/* file type is default */
					report.docType = "file";
				}

			if ( report.repeat <= 0 )
			{
				System.err.println( "invalid repeat: " + report.repeat );
				/* 1 is default */
				report.repeat = 1;
			}

			if ( instance.getReportDesign( id ) != null )
			{
				System.err.println( "Duplicate report ids: " + id ); //$NON-NLS-1$
			}

			instance.addReportDesign( report );
		}

		for ( int i = 0; i < testcases.getLength( ); i++ )
		{
			Element testcase = (Element) testcases.item( i );
			String name = testcase.getAttribute( NAME_ATTR );
			String locale = Utility.getFirstChildValue( testcase, LOCALE_TAG );
			String encoding = Utility.getFirstChildValue( testcase,
					ENCODING_TAG );
			String format = Utility.getFirstChildValue( testcase, FORMAT_TAG );
			String reports = Utility.getFirstChildValue( testcase, REPORTS_TAG );
			int threads = Integer.parseInt( Utility.getFirstChildValue( testcase,
					THREADS_TAG ) );
			String tasklist = Utility.getFirstChildValue( testcase, TASKS_TAG );

			String[] tasks = tasklist.split( "," );

			for ( int index = 0; index < tasks.length; index++ )
			{
				String task = tasks[index].trim( );
				if ( !task.equalsIgnoreCase( "run" ) )
					if ( !task.equalsIgnoreCase( "renderAll" ) )
						if ( !task.equalsIgnoreCase( "renderN" ) )
							if ( !task.equalsIgnoreCase( "runandrender" ) )
							{
								System.err.println( "invalid task list:"
										+ tasklist );
								return;
							}
			}

			// "1", "5" or "1,2,3,5" or "1-10" or "all"

			boolean valid = Pattern.matches( "[\\d]+[,\\d]*|[A|a]ll|[\\d]+-[\\d]+", reports ); //$NON-NLS-1$

			if ( !valid )
			{
				System.err.println( "\"reports\" value not valid, use format like \"1\", \"5\" or \"1,2,3\" or \"1-10\" or \"all\" " ); //$NON-NLS-1$
				System.err.println( "Change reports value to default \"All\"" ); //$NON-NLS-1$
				reports = "All"; //$NON-NLS-1$
			}

			TestCaseNode testcaseNode = new TestCaseNode( );
			testcaseNode.name = name;
			testcaseNode.encoding = encoding;
			testcaseNode.locale = locale;
			testcaseNode.report = reports;
			testcaseNode.threads = threads;
			testcaseNode.format = format;
			testcaseNode.tasks = tasks;

			instance.addTestCase( testcaseNode );
		}

		instance.build( );
	}

	/**
	 * parseFile, parse config. profile
	 * 
	 * @param fileName -
	 *            testcase configuration file
	 * @throws FileNotFoundException
	 */

	public static void parse( String fileName ) throws Exception
	{
		parse( new FileInputStream( new File( fileName ) ) );
	}

}
