/*******************************************************************************
 * 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.report.designer.internal.ui.views.attributes.page;

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

import org.eclipse.birt.report.designer.nls.Messages;
import org.eclipse.birt.report.designer.ui.views.attributes.ICategoryPage;
import org.eclipse.birt.report.designer.ui.views.attributes.TabPage;
import org.eclipse.birt.report.designer.ui.views.attributes.providers.ICategoryProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;

/**
 * The container page of AttributePages.
 */
public class BaseAttributePage extends TabPage
{

	/**
	 * The list control contains categories of a DE element attributes.
	 */
	private org.eclipse.swt.widgets.List categoryList;

	/**
	 * Label control to show category information.
	 */
	private Label categoryInfoLabel;

	/**
	 * Container that material category attribute page will reside in.
	 */
	private Composite infoPane;

	/**
	 * ICategoryProvider instance, responds to the selection changing in the
	 * categoryList.
	 */
	private ICategoryProvider categoryProvider;

	/**
	 * The Last Selected index in the list of categories
	 */
	private static int s_lastSelectedIndex = 0;

	/**
	 * The last selected title in the list of categories
	 */
	private static String s_lastSelectedTitle = null;
	/**
	 * The current selection.
	 */
	private List input = new ArrayList( );

	/**
	 * The map keeps the relationships between category label & pane
	 */
	private HashMap pageMap;

	private ScrolledComposite sComposite;

	private TabPage currentPage = null;

	/**
	 * Constructor
	 * 
	 * @param parent
	 *            A widget which will be the parent of the new instance (cannot
	 *            be null)
	 * @param style
	 *            The style of widget to construct
	 */
	public BaseAttributePage( Composite parent, int style )
	{
		super( parent, style );
		buildUI( );
	}

	/**
	 * Creates UI control.
	 * 
	 */
	protected void buildUI( )
	{
		setLayout( new GridLayout( 2, false ) );

		Label label = new Label( this, SWT.NONE );
		label.setText( Messages.getString( "BasAttributePage.Label.Attributes" ) ); //$NON-NLS-1$

		categoryInfoLabel = new Label( this, SWT.NONE );
		GridData gd = new GridData( GridData.FILL_HORIZONTAL );
		categoryInfoLabel.setLayoutData( gd );

		Label separator = new Label( this, SWT.SEPARATOR | SWT.H_SCROLL );
		gd = new GridData( GridData.FILL_HORIZONTAL );
		gd.horizontalSpan = 2;
		separator.setLayoutData( gd );

		categoryList = new org.eclipse.swt.widgets.List( this, SWT.SINGLE
				| SWT.BORDER
				| SWT.H_SCROLL
				| SWT.V_SCROLL );
		gd = new GridData( GridData.FILL_VERTICAL );
		gd.widthHint = 150;
		categoryList.setLayoutData( gd );
		categoryList.addSelectionListener( new SelectionAdapter( ) {

			public void widgetSelected( SelectionEvent e )
			{
				if ( categoryList.getSelection( ).length > 0 )
				{
					BaseAttributePage.s_lastSelectedTitle = categoryList.getSelection( )[0];
					BaseAttributePage.s_lastSelectedIndex = categoryList.getSelectionIndex( );
				}
				processListSelected( );
			}
		} );

		sComposite = new ScrolledComposite( this, SWT.H_SCROLL | SWT.V_SCROLL );
		sComposite.setLayoutData( new GridData( GridData.FILL_BOTH ) );
		sComposite.setExpandHorizontal( true );
		sComposite.setExpandVertical( true );
		sComposite.addControlListener( new ControlAdapter( ) {

			public void controlResized( ControlEvent e )
			{
				computeSize( );
			}
		} );
		infoPane = new Composite( sComposite, SWT.NONE );
		sComposite.setContent( infoPane );
		infoPane.setLayout( new GridLayout( ) );
	}

	private void computeSize( )
	{
		sComposite.setMinSize( infoPane.computeSize( SWT.DEFAULT, SWT.DEFAULT ) );
		infoPane.layout( );
	}

	/**
	 * When selection changed in the category list, re-sets the top-level
	 * category pane correspond to the current selected category.
	 */
	private void processListSelected( )
	{
		if ( categoryProvider == null )
		{
			return;
		}
		String[] values = categoryList.getSelection( );
		if ( values == null || values.length == 0 )
		{
			return;
		}

		categoryInfoLabel.setText( values[0] );
		TabPage page = getCategoryPane( categoryList.getSelectionIndex( ) );
		if ( page == null )
		{
			return;
		}
		page.setInput( input );
		showPage( page );
	}

	private void showPage( TabPage page )
	{
		if ( page != currentPage )
		{
			if ( currentPage != null )
			{
				( (GridData) currentPage.getLayoutData( ) ).exclude = true;
				currentPage.setVisible( false );
			}
			( (GridData) page.getLayoutData( ) ).exclude = false;
			page.setVisible( true );
			currentPage = page;
			computeSize( );
		}
	}

	protected void selectStickyCategory( )
	{
		boolean found = false;
		// select the last item that was selected by the user. If out of
		// bounds select the last one
		if ( s_lastSelectedTitle != null )
		{
			String[] items = categoryList.getItems( );
			for ( int i = 0; i < items.length; i++ )
			{
				if ( items[i].equals( s_lastSelectedTitle ) )
				{
					found = true;
					categoryList.select( i );
					break;
				}
			}
		}
		if ( !found )
		{
			if ( s_lastSelectedIndex > categoryList.getItemCount( ) - 1 )
			{
				categoryList.setSelection( categoryList.getItemCount( ) - 1 );
			}
			else
			{
				categoryList.setSelection( s_lastSelectedIndex );
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.birt.report.designer.ui.attributes.component.TabPage#setInput(java.util.List)
	 */
	public void setInput( java.util.List input )
	{
		this.input = input;
		selectStickyCategory( );
		processListSelected( );
	}

	/**
	 * Sets CategoryProvider
	 * 
	 * @param categoryProvider
	 *            The categoryListener to set.
	 */
	public void setCategoryProvider( ICategoryProvider categoryProvider )
	{
		this.categoryProvider = categoryProvider;
		if ( categoryProvider == null )
		{
			categoryList.setItems( new String[0] );
			return;
		}
		ICategoryPage[] pages = categoryProvider.getCategories( );
		if ( pages.length != 0 )
		{
			String[] categoryLabels = new String[pages.length];
			for ( int i = 0; i < pages.length; i++ )
			{
				categoryLabels[i] = pages[i].getDisplayLabel( );
			}
			categoryList.setItems( categoryLabels );
			if ( categoryList.getItemCount( ) > 0 )
			{
				categoryList.select( 0 );
			}
		}
		else
		{
			categoryList.setItems( new String[0] );
		}
	}

	private TabPage getCategoryPane( int index )
	{
		if ( pageMap == null )
		{
			pageMap = new HashMap( categoryProvider.getCategories( ).length );
		}
		String key = Integer.toString( index );
		TabPage page = (TabPage) pageMap.get( key );
		if ( page == null )
		{
			page = categoryProvider.getCategories( )[index].createControl( infoPane,
					SWT.NONE );
			page.setLayoutData( new GridData( GridData.FILL_BOTH ) );
			pageMap.put( key, page );
		}
		return page;
	}

}