/*******************************************************************************
 * Copyright (c) 2004, 2005 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.report.designer.data.ui.datasource;

import java.util.Properties;

import org.eclipse.birt.report.designer.data.ui.util.DTPUtil;
import org.eclipse.birt.report.designer.data.ui.util.Utility;
import org.eclipse.birt.report.designer.internal.ui.util.ExceptionHandler;
import org.eclipse.birt.report.designer.nls.Messages;
import org.eclipse.birt.report.model.adapter.oda.ModelOdaAdapter;
import org.eclipse.birt.report.model.api.CommandStack;
import org.eclipse.birt.report.model.api.DataSourceHandle;
import org.eclipse.birt.report.model.api.DesignElementHandle;
import org.eclipse.birt.report.model.api.ModuleHandle;
import org.eclipse.birt.report.model.api.SlotHandle;
import org.eclipse.birt.report.model.api.activity.SemanticException;
import org.eclipse.core.runtime.Path;
import org.eclipse.datatools.connectivity.oda.OdaException;
import org.eclipse.datatools.connectivity.oda.design.DataSourceDesign;
import org.eclipse.datatools.connectivity.oda.design.ui.designsession.DataSourceDesignSession;
import org.eclipse.jface.wizard.Wizard;

/**
 * 
 */

public class ConnectionProfileWizard extends Wizard
{

	private ConnectionProfileSelectionPage page = null;
	private DataSourceDesignSession m_designSession = null;
	private DataSourceDesign dataSourceDesign = null;
	private DesignElementHandle parentHandle = null;
	private DataSourceHandle dataSourceHandle = null;
	private static ConnectionProfileWizard instance = null;
	private static final String CREATE_DATA_SOURCE_TRANS_NAME = Messages.getString( "wizard.transaction.createDataSource" ); //$NON-NLS-1$

	public static final String DATA_SOURCE_NAME = "newDataSourceName";
	public static final String PROFILE_INSTANCE_ID = "profileInstanceId";
	public static final String STOREAGE_FILE_PATH = "storageFilePath";
	public static final String DATA_SOURCE_ID = "odaDataSourceID";

	public static synchronized ConnectionProfileWizard getInstance( )
	{
		if ( instance == null )
			instance = new ConnectionProfileWizard( );

		return instance;
	}

	public ConnectionProfileWizard( )
	{
		addPages( );
		setWindowTitle( Messages.getString( "connectionprofile.wizard.title" ) );
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.wizard.Wizard#addPages()
	 */
	public void addPages( )
	{
		page = new ConnectionProfileSelectionPage( Messages.getString( "connectionprofile.wizard.title.connectionprofileselect" ) );
		addPage( page );
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.wizard.Wizard#performFinish()
	 */
	public boolean performFinish( )
	{
		init( );

		if ( isCustomPageUsed( ) )
			createFromCustomPage( );
		else
			createFromConnectionProfile( );

		tearDown( );

		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.wizard.Wizard#performCancel()
	 */
	public boolean performCancel( )
	{
		if ( m_designSession != null )
		{
			m_designSession.cancel( );
			m_designSession = null; // reset; done with this session
		}

		resetCPWizard( );

		return super.performCancel( );
	}

	/**
	 * To start a Model transaction and create parentHandle
	 * 
	 */
	private void init( )
	{
		getActivityStack( ).startTrans( CREATE_DATA_SOURCE_TRANS_NAME );
		parentHandle = Utility.getReportModuleHandle( );
	}

	/**
	 * check if custom page has been used
	 * 
	 * @return
	 */
	private boolean isCustomPageUsed( )
	{
		m_designSession = page.getDataSourceDesignSession( );

		if ( m_designSession != null )
			return true;
		else
			return false;
	}

	/**
	 * create dataSourceHandle from custom page
	 * 
	 */
	private void createFromCustomPage( )
	{
		try
		{
			dataSourceHandle = DTPUtil.getInstance( )
					.createOdaDataSourceHandle( m_designSession.finish( )
							.getResponse( ),
							(ModuleHandle) parentHandle );
			m_designSession = null;
		}
		catch ( OdaException e )
		{
			ExceptionHandler.handle( e );
		}
		catch ( SemanticException e )
		{
            ExceptionHandler.handle( e );
		}
	}

	/**
	 * create dataSourceHandle from ConnectionProfile
	 * 
	 */
	private void createFromConnectionProfile( )
	{
		Properties cpProperties = page.getCPProperties( );

		String odaDataSourceID = cpProperties.getProperty( DATA_SOURCE_ID );
		String newDataSourceName = cpProperties.getProperty( DATA_SOURCE_NAME );

		DataSourceDesignSession.ProfileReference profileRef = new DataSourceDesignSession.ProfileReference( cpProperties.getProperty( PROFILE_INSTANCE_ID ),
				new Path( cpProperties.getProperty( STOREAGE_FILE_PATH ) ).toFile( ),
				false );

		try
		{
			dataSourceDesign = DataSourceDesignSession.createNewDesignFromProfile( odaDataSourceID,
					newDataSourceName,
					profileRef )
					.getResponseDataSourceDesign( );
			dataSourceHandle = new ModelOdaAdapter( ).createDataSourceHandle( dataSourceDesign,
					(ModuleHandle) parentHandle );
		}
		catch ( OdaException e )
		{
			ExceptionHandler.handle( e );
		}
		catch ( SemanticException e )
		{
			ExceptionHandler.handle( e );
		}
	}

	/**
	 * Add the created dataSourceHandle to SlotHandle and commit it to Model
	 * 
	 */
	private void tearDown( )
	{
		// in case users click next and back and finish
		if ( dataSourceHandle == null )
			createFromConnectionProfile( );

		try
		{
			SlotHandle slotHandle = ( (ModuleHandle) parentHandle ).getDataSources( );
			slotHandle.add( dataSourceHandle );
		}
		catch ( SemanticException e )
		{
			getActivityStack( ).rollback( );
			ExceptionHandler.handle( e );
		}

		resetCPWizard( );
		getActivityStack( ).commit( );

	}

	/**
	 * reset the connection profile wizard
	 * 
	 */
	private void resetCPWizard( )
	{
		instance = null;
	}

	private CommandStack getActivityStack( )
	{
		return Utility.getCommandStack( );
	}

}
