/*******************************************************************************
 * 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.data.ui.dataset;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

import org.eclipse.birt.core.data.ExpressionUtil;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.report.designer.data.ui.util.ControlProvider;
import org.eclipse.birt.report.designer.data.ui.util.DataSetExpressionProvider;
import org.eclipse.birt.report.designer.data.ui.util.SelectValueFetcher;
import org.eclipse.birt.report.designer.internal.ui.util.IHelpContextIds;
import org.eclipse.birt.report.designer.internal.ui.util.UIUtil;
import org.eclipse.birt.report.designer.internal.ui.util.WidgetUtil;
import org.eclipse.birt.report.designer.nls.Messages;
import org.eclipse.birt.report.designer.ui.dialogs.ExpressionBuilder;
import org.eclipse.birt.report.designer.ui.dialogs.IExpressionProvider;
import org.eclipse.birt.report.designer.ui.dialogs.SelectValueDialog;
import org.eclipse.birt.report.designer.ui.views.attributes.providers.ChoiceSetFactory;
import org.eclipse.birt.report.designer.ui.widget.PopupSelectionList;
import org.eclipse.birt.report.designer.util.DEUtil;
import org.eclipse.birt.report.model.api.DataSetHandle;
import org.eclipse.birt.report.model.api.DesignElementHandle;
import org.eclipse.birt.report.model.api.FilterConditionHandle;
import org.eclipse.birt.report.model.api.ParamBindingHandle;
import org.eclipse.birt.report.model.api.elements.DesignChoiceConstants;
import org.eclipse.birt.report.model.api.elements.structures.FilterCondition;
import org.eclipse.birt.report.model.api.metadata.IChoice;
import org.eclipse.birt.report.model.api.metadata.IChoiceSet;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;

/**
 * Dialog for adding or editing map rule.
 */

class FilterConditionBuilder extends PropertyHandleInputDialog
{
	protected FilterConditionBuilder( Object structureOrHandle )
	{
		super( structureOrHandle );
		this.inputHandle = this.getStructureOrHandle( );
	}


	private static String[] cellLabels = new String[]{
		Messages.getString( "dataset.editor.inputDialog.expression" ),//$NON-NLS-1$
		Messages.getString( "dataset.editor.inputDialog.operator" ),//$NON-NLS-1$
		Messages.getString( "dataset.editor.inputDialog.value1" ),//$NON-NLS-1$
		Messages.getString( "dataset.editor.inputDialog.value2" )//$NON-NLS-1$
	};
	protected static Logger logger = Logger.getLogger( FilterConditionBuilder.class.getName( ) );

	public static final String DLG_TITLE_NEW = Messages.getString( "FilterConditionBuilder.DialogTitle.New" ); //$NON-NLS-1$
	public static final String DLG_TITLE_EDIT = Messages.getString( "FilterConditionBuilder.DialogTitle.Edit" ); //$NON-NLS-1$
	public static final String DLG_MESSAGE_NEW = Messages.getString( "FilterConditionBuilder.DialogMessage.New" ); //$NON-NLS-1$
	public static final String DLG_MESSAGE_EDIT = Messages.getString( "FilterConditionBuilder.DialogMessage.Edit" ); //$NON-NLS-1$

	protected transient String[] popupItems = null;

	private static String[] actions = new String[]{
			Messages.getString( "ExpressionValueCellEditor.selectValueAction" ), //$NON-NLS-1$
			Messages.getString( "ExpressionValueCellEditor.buildExpressionAction" ), //$NON-NLS-1$
	};

	protected Label label1, label2;
	protected Label valueLabel1, valueLabel2;
	protected List valueList = new ArrayList( );
	/**
	 * Usable operators for building map rule conditions.
	 */
	protected static final String[][] OPERATOR;

	private transient String bindingName;

	private ParamBindingHandle[] bindingParams = null;

	private transient boolean refreshItems = true;

	protected transient DataSetHandle currentItem = null;

	protected static String[] EMPTY_ARRAY = new String[]{};

	protected int valueVisible;

	protected Table table;
	protected TableViewer tableViewer;


	/**
	 * @param bindingName
	 *            The selectValueExpression to set.
	 */
	public void setBindingName( String bindingName )
	{
		this.bindingName = bindingName;
	}

	/**
	 * 
	 */
	public void setBindingParams( Iterator parameters )
	{
		if ( parameters == null )
			return;
		List params = new ArrayList();
		while( parameters.hasNext( ))
		{
			params.add( parameters.next( ) );
		}
		
		this.bindingParams = new ParamBindingHandle[params.size( )];
		for( int i = 0; i < this.bindingParams.length; i++ )
		{
			this.bindingParams[i] = (ParamBindingHandle)params.get( i );
		}
	}


	protected IChoiceSet choiceSet;

	static
	{
		IChoiceSet chset = ChoiceSetFactory.getStructChoiceSet( FilterCondition.FILTER_COND_STRUCT,
				FilterCondition.OPERATOR_MEMBER);
		IChoice[] chs = chset.getChoices( );
		OPERATOR = new String[chs.length][2];

		for ( int i = 0; i < chs.length; i++ )
		{
			OPERATOR[i][0] = chs[i].getDisplayName( );
			OPERATOR[i][1] = chs[i].getName( );
		}
	}

	/**
	 * Returns the operator value by its display name.
	 * 
	 * @param name
	 */
	public static String getValueForOperator( String name )
	{
		for ( int i = 0; i < OPERATOR.length; i++ )
		{
			if ( OPERATOR[i][0].equals( name ) )
			{
				return OPERATOR[i][1];
			}
		}

		return null;
	}

	/**
	 * Returns how many value fields this operator needs.
	 * 
	 * @param operatorValue
	 */
	public static int determineValueVisible( String operatorValue )
	{
		if ( DesignChoiceConstants.FILTER_OPERATOR_ANY.equals( operatorValue )
				|| DesignChoiceConstants.FILTER_OPERATOR_FALSE.equals( operatorValue )
				|| DesignChoiceConstants.FILTER_OPERATOR_TRUE.equals( operatorValue )
				|| DesignChoiceConstants.FILTER_OPERATOR_NULL.equals( operatorValue )
				|| DesignChoiceConstants.FILTER_OPERATOR_NOT_NULL.equals( operatorValue ) )
		{
			return 0;
		}
		else if ( DesignChoiceConstants.FILTER_OPERATOR_LT.equals( operatorValue )
				|| DesignChoiceConstants.FILTER_OPERATOR_LE.equals( operatorValue )
				|| DesignChoiceConstants.FILTER_OPERATOR_EQ.equals( operatorValue )
				|| DesignChoiceConstants.FILTER_OPERATOR_NE.equals( operatorValue )
				|| DesignChoiceConstants.FILTER_OPERATOR_GE.equals( operatorValue )
				|| DesignChoiceConstants.FILTER_OPERATOR_GT.equals( operatorValue )
				|| DesignChoiceConstants.FILTER_OPERATOR_LIKE.equals( operatorValue ) )
		{
			return 1;
		}
		else if ( DesignChoiceConstants.FILTER_OPERATOR_BETWEEN.equals( operatorValue )
				|| DesignChoiceConstants.FILTER_OPERATOR_NOT_BETWEEN.equals( operatorValue ) )
		{
			return 2;
		}
		else if ( DesignChoiceConstants.FILTER_OPERATOR_IN.equals( operatorValue )
				|| DesignChoiceConstants.MAP_OPERATOR_NOT_IN.equals( operatorValue ) )
		{
			return 3;
		}

		return 1;
	}

	/**
	 * Returns the operator display name by its value.
	 * 
	 * @param value
	 */
	public static String getNameForOperator( String value )
	{
		for ( int i = 0; i < OPERATOR.length; i++ )
		{
			if ( OPERATOR[i][1].equals( value ) )
			{
				return OPERATOR[i][0];
			}
		}

		return ""; //$NON-NLS-1$
	}

	/**
	 * Returns the index for given operator value in the operator list.
	 * 
	 * @param value
	 */
	protected static int getIndexForOperatorValue( String value )
	{
		for ( int i = 0; i < OPERATOR.length; i++ )
		{
			if ( OPERATOR[i][1].equals( value ) )
			{
				return i;
			}
		}

		return 0;
	}

//	protected FilterConditionHandle inputHandle;

	protected Combo expression, operator;

	protected Button valBuilder1, valBuilder2;

	protected Button addBtn, editBtn, delBtn, delAllBtn;

	protected ExpressionValue expressionValue1, expressionValue2,
			addExpressionValue;

	protected Composite valueListComposite;

	protected Text value1, value2;

	protected Label value1Label;
	protected Label value2Label;
	//protected DesignElementHandle designHandle;

	protected static final String VALUE_OF_THIS_DATA_ITEM = Messages.getString( "FilterConditionBuilder.choice.ValueOfThisDataItem" ); //$NON-NLS-1$

	private String[] dataSetColumns;

	private Object inputHandle;

	
	protected void createFilterConditionContent( Composite innerParent )
	{
		Label lb = new Label( innerParent, SWT.NONE );
		lb.setText( Messages.getString( "FilterConditionBuilder.text.Condition" ) ); //$NON-NLS-1$*/

		Composite condition = new Composite( innerParent, SWT.NONE );
		
		GridData gd = new GridData( GridData.FILL_BOTH) ;
		gd.grabExcessVerticalSpace = true;
		gd.horizontalSpan = 3;
		gd.widthHint = 400;
		gd.heightHint = 200;
		condition.setLayoutData( gd );
		GridLayout glayout = new GridLayout( 3, false );
		condition.setLayout( glayout );
		
		ControlProvider.createLabel( condition, cellLabels[0] );
		
		Composite composite = ControlProvider.getDefaultComposite( condition );
		expression = new Combo( composite, SWT.NONE );
		expression.setLayoutData( ControlProvider.getGridDataWithHSpan( 1 ) );
		expression.addListener( SWT.Selection, ComboModify );
		expression.setItems( this.dataSetColumns );
		
		if ( expression.getItemCount( ) == 0 )
		{
			expression.add( DEUtil.resolveNull( null ) );
		}
		
		expression.addModifyListener( new ModifyListener( ) {

			public void modifyText( ModifyEvent e )
			{
				updateButtons( );
			}
		} );

		
		createExpressionBuilder( composite, expression );

		ControlProvider.createLabel( condition, cellLabels[1] );
		
		composite = ControlProvider.getDefaultComposite( condition );
		operator = new Combo( composite, SWT.READ_ONLY );
		for ( int i = 0; i < OPERATOR.length; i++ )
		{
			operator.add( OPERATOR[i][0] );
		}
		gd = ControlProvider.getGridDataWithHSpan( 1 );
		operator.setLayoutData( gd );
		operator.addSelectionListener( OpoertorSelection );

		create2ValueComposite( condition );

		if ( inputHandle != null )
		{
			syncViewProperties( );
		}

		new Label( innerParent, SWT.SEPARATOR | SWT.HORIZONTAL ).setLayoutData( ControlProvider.getGridDataWithHSpan( 2 ) );
		
	}

	private void createExpressionBuilder( Composite condition, final Control c )
	{
		Button expBuilder = new Button( condition, SWT.PUSH );
		UIUtil.setExpressionButtonImage( expBuilder );
		expBuilder.setToolTipText( Messages.getString( "FilterConditionBuilder.tooltip.ExpBuilder" ) ); //$NON-NLS-1$
		expBuilder.addSelectionListener( new SelectionAdapter( ) {

			public void widgetSelected( SelectionEvent e )
			{
				editValue( c );
			}
		} );
	}

	public void setDataSetColumns( String[] dataSetColumns )
	{
		this.dataSetColumns = dataSetColumns;
	}
	
	private void create2ValueComposite( Composite condition )
	{
		if ( expressionValue1 != null && !expressionValue1.isDisposed( ) )
		{
			return;
		}

		if ( valueListComposite != null && !valueListComposite.isDisposed( ) )
		{
			valueListComposite.dispose( );
			valueListComposite = null;
		}

		this.valueLabel1 = ControlProvider.createLabel( condition, cellLabels[2] );
		
		expressionValue1 = new ExpressionValue( condition, SWT.NONE, expression );
		value1 = expressionValue1.getValueText( );
		valBuilder1 = expressionValue1.getPopupButton( );
		value1.setLayoutData( ControlProvider.getGridDataWithHSpan( 1 ) );
		valBuilder1.setLayoutData( ControlProvider.getGridDataWithHSpan( 1 ) );

		this.valueLabel2 = ControlProvider.createLabel( condition, cellLabels[3] );
		
		expressionValue2 = new ExpressionValue( condition, SWT.NONE, expression );
		value2 = expressionValue2.getValueText( );
		valBuilder2 = expressionValue2.getPopupButton( );
		value2.setLayoutData( ControlProvider.getGridDataWithHSpan( 1 ) );
		valBuilder2.setLayoutData( ControlProvider.getGridDataWithHSpan( 1 ) );
		
		if ( operator.getItemCount( ) > 0 && operator.getSelectionIndex( ) == -1)
		{
			operator.select( 0 );
		}
		
		condition.getParent( ).layout( true, true );

	}

	private void createValueListComposite( Composite parent )
	{
		parent.setEnabled( true );
		if ( valueListComposite != null && !valueListComposite.isDisposed( ) )
		{
			return;
		}

		if ( expressionValue1 != null && !expressionValue1.isDisposed( ) )
		{
			expressionValue1.dispose( );
			expressionValue1 = null;

			expressionValue2.dispose( );
			expressionValue2 = null;
			
			valueLabel1.dispose( );
			valueLabel1 = null;
			
			valueLabel2.dispose( );
			valueLabel2 = null;

		}

		valueListComposite = new Composite( parent, SWT.NONE );
		GridData gdata = new GridData( GridData.FILL_HORIZONTAL );
		gdata.horizontalSpan = 4;
		valueListComposite.setLayoutData( gdata );
		GridLayout layout = new GridLayout( );
		layout.numColumns = 4;
		layout.marginWidth = 0;
		layout.marginLeft = 0;
		layout.marginRight = 0;
		valueListComposite.setLayout( layout );

		createValueTable( valueListComposite );

		Composite rightPart = new Composite( valueListComposite, SWT.NONE );
		GridData data = new GridData( GridData.FILL_BOTH );
		rightPart.setLayoutData( data );
		layout = new GridLayout( );
		layout.makeColumnsEqualWidth = true;
		rightPart.setLayout( layout );

		editBtn = new Button( rightPart, SWT.PUSH );
		editBtn.setText( Messages.getString( "FilterConditionBuilder.button.edit" )); //$NON-NLS-1$
		editBtn.setToolTipText( Messages.getString( "FilterConditionBuilder.button.edit.tooltip"  )); //$NON-NLS-1$
		setButtonLayoutData( editBtn );
		editBtn.addSelectionListener( new SelectionListener( ) {

			public void widgetDefaultSelected( SelectionEvent e )
			{
				// TODO Auto-generated method stub

			}

			public void widgetSelected( SelectionEvent e )
			{
				// TODO Auto-generated method stub
				IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection( );
				if ( selection.getFirstElement( ) != null
						&& selection.getFirstElement( ) instanceof String )
				{
					String initValue = (String) selection.getFirstElement( );

					ExpressionBuilder expressionBuilder = new ExpressionBuilder( getShell( ),
							initValue );

					expressionBuilder.setExpressionProvier( expressionProvider );
			
					if ( expressionBuilder.open( ) == OK )
					{
						String result = DEUtil.resolveNull( expressionBuilder.getResult( ) );
						if ( result == null || result.trim( ).length( ) == 0 )
						{
							MessageDialog.openWarning( tableViewer.getControl( )
									.getShell( ),
									Messages.getString( "dataset.editor.error.title" ), //$NON-NLS-1$
									Messages.getString( "dataset.error.emptyexpression" ) ); //$NON-NLS-1$
						}
						else
						{
							int index = table.getSelectionIndex( );
							valueList.remove( index );
							valueList.add( index, result );
							tableViewer.refresh( );
							table.select( index );
						}
					}
					updateButtons( );
				}
				else
				{
					editBtn.setEnabled( false );
				}
			}

		} );

		delBtn = new Button( rightPart, SWT.PUSH );
		delBtn.setText( Messages.getString( "FilterConditionBuilder.button.delete" ) ); //$NON-NLS-1$
		delBtn.setToolTipText( Messages.getString( "FilterConditionBuilder.button.delete.tooltip" ) ); //$NON-NLS-1$
		setButtonLayoutData( delBtn );
		delBtn.addSelectionListener( new SelectionListener( ) {

			public void widgetDefaultSelected( SelectionEvent e )
			{
				// TODO Auto-generated method stub

			}

			public void widgetSelected( SelectionEvent e )
			{
				// TODO Auto-generated method stub
				int index = table.getSelectionIndex( );
				if ( index > -1 )
				{
					valueList.remove( index );
					tableViewer.refresh( );
					if ( valueList.size( ) > 0 )
					{
						if ( valueList.size( ) <= index )
						{
							index = index - 1;
						}
						table.select( index );
					}
					updateButtons( );
				}
				else
				{
					delBtn.setEnabled( false );
				}
			}

		} );

		delAllBtn = new Button( rightPart, SWT.PUSH );
		delAllBtn.setText( Messages.getString("FilterConditionBuilder.button.deleteall")); //$NON-NLS-1$
		delAllBtn.setToolTipText(Messages.getString("FilterConditionBuilder.button.deleteall.tooltip" )); //$NON-NLS-1$
		setButtonLayoutData( delAllBtn );
		delAllBtn.addSelectionListener( new SelectionListener(){

			public void widgetDefaultSelected( SelectionEvent e )
			{
				// TODO Auto-generated method stub
				
			}

			public void widgetSelected( SelectionEvent e )
			{
				// TODO Auto-generated method stub
				int count = valueList.size( );
				if(count > 0)
				{
					valueList.clear( );
					tableViewer.refresh( );
					updateButtons();
				}else
				{
					delAllBtn.setEnabled( false );
				}
			}
			
		} );
		parent.getParent( ).layout( true, true );
	}

	private void createAddButton(Composite container )
	{
		Label valueLabel = new Label(container, SWT.BOTTOM|SWT.CENTER );
		valueLabel.setText( Messages.getString( "FilterConditionBuilder.list.item1" ) ); //$NON-NLS-1$
		addExpressionValue = new ExpressionValue( container,
				SWT.NONE,
				expression );

		addExpressionValue.getValueText( )
				.addModifyListener( new ModifyListener( ) {

					public void modifyText( ModifyEvent e )
					{
						checkAddButtonStatus( );
					}
				} );
		addBtn = new Button( container, SWT.PUSH );
		addBtn.setText( Messages.getString( "FilterConditionBuilder.button.add" ) ); //$NON-NLS-1$
		addBtn.setToolTipText(Messages.getString( "FilterConditionBuilder.button.add.tooltip" ) ); //$NON-NLS-1$
		addBtn.addSelectionListener( new SelectionListener( ) {

			public void widgetDefaultSelected( SelectionEvent e )
			{
				// TODO Auto-generated method stub

			}

			public void widgetSelected( SelectionEvent e )
			{
				// TODO Auto-generated method stub
				String value = addExpressionValue.getValueText( ).getText( );
				if ( valueList.indexOf( value ) < 0 )
				{
					valueList.add( value );
					tableViewer.refresh( );
					updateButtons( );
					addExpressionValue.getValueText( ).setFocus( );
					addExpressionValue.getValueText( ).setText( "" ); //$NON-NLS-1$
				}
				else
				{
					addBtn.setEnabled( false );
				}

			}
		} );
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.window.Window#create()
	 */
	public void create( )
	{
		super.create( );

		Point pt = getShell( ).computeSize( -1, -1 );
		pt.x = Math.max( pt.x, 400 );
		pt.y = Math.max( pt.y, 365 );
		getShell( ).setSize( pt );
		getShell( ).setText( getTitle( ) );
	}

	private void createValueTable( Composite parent )
	{
		Group container = new Group( parent, SWT.NONE );
		GridData gdata = new GridData( GridData.FILL_HORIZONTAL );
		gdata.horizontalSpan = 3;
		container.setLayoutData( gdata );
		GridLayout layout = new GridLayout( );
		layout.numColumns = 4;
		layout.marginWidth = 3;
		layout.marginLeft = 0;
		layout.marginRight = 0;
		container.setLayout( layout );

		createAddButton( container );
		createTable( container );
	}

	private void createTable( Composite container )
	{
		int tableStyle = SWT.SINGLE
				| SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION;
		table = new Table( container, tableStyle );
		GridData data = new GridData( );
		data.heightHint = 80;
		data.horizontalSpan = 4;
		data.grabExcessHorizontalSpace = true;
		table.setLayoutData( data );

		table.setHeaderVisible( false );
		table.setLinesVisible( true );
		TableColumn column;
		int i;
		String[] columNames = new String[]{
			Messages.getString( "FilterConditionBuilder.list.item1" ), //$NON-NLS-1$
		};
		int[] columLength = new int[]{
			250
		};
		for ( i = 0; i < columNames.length; i++ )
		{
			column = new TableColumn( table, SWT.NONE, i );
			column.setText( columNames[i] );
			column.setWidth( columLength[i] );
		}
		addListenerForTable( );
		tableViewer = new TableViewer( table );
		tableViewer.setUseHashlookup( true );
		tableViewer.setLabelProvider( tableLableProvier );
		tableViewer.setContentProvider( tableContentProvider );
	}

	private void addListenerForTable() {
		table.addSelectionListener( new SelectionListener( ) {

			public void widgetDefaultSelected( SelectionEvent e )
			{
				// TODO Auto-generated method stub
			}

			public void widgetSelected( SelectionEvent e )
			{
				// TODO Auto-generated method stub
				checkEditDelButtonStatus( );
			}
		} );

		table.addKeyListener( new KeyListener( ) {

			public void keyPressed( KeyEvent e )
			{
				// TODO Auto-generated method stub
				if ( e.keyCode == SWT.DEL )
				{
					int index = table.getSelectionIndex( );
					if ( index > -1 )
					{
						valueList.remove( index );
						tableViewer.refresh( );
						if ( valueList.size( ) > 0 )
						{
							if ( valueList.size( ) <= index )
							{
								index = index - 1;
							}
							table.select( index );
						}
						updateButtons( );
					}
					else
					{
						delBtn.setEnabled( false );
					}
				}

			}

			public void keyReleased( KeyEvent e )
			{
				// TODO Auto-generated method stub

			}

		} );
		table.addMouseListener( new MouseAdapter( ) {

			public void mouseDoubleClick( MouseEvent e )
			{
				IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection( );
				if ( selection.getFirstElement( ) != null
						&& selection.getFirstElement( ) instanceof String )
				{
					String initValue = (String) selection.getFirstElement( );

					ExpressionBuilder expressionBuilder = new ExpressionBuilder( getShell( ),
							initValue );

					expressionBuilder.setExpressionProvier( expressionProvider );
		
					if ( expressionBuilder.open( ) == OK )
					{
						String result = DEUtil.resolveNull( expressionBuilder.getResult( ) );
						if (  result == null || result.trim( ).length( ) == 0 )
						{
							MessageDialog.openWarning( tableViewer.getControl( )
									.getShell( ),
									Messages.getString( "dataset.editor.error.title" ), //$NON-NLS-1$
									Messages.getString( "dataset.error.emptyexpression" ) ); //$NON-NLS-1$
						}
						else
						{
							int index = table.getSelectionIndex( );
							valueList.remove( index );
							valueList.add( index, result );
							tableViewer.refresh( );
							table.select( index );
						}
					}
					updateButtons( );
				}
				else
				{
					editBtn.setEnabled( false );
				}
			}
		} );
	}

	protected ITableLabelProvider tableLableProvier = new ITableLabelProvider( ) {

		public Image getColumnImage( Object element, int columnIndex )
		{
			// TODO Auto-generated method stub
			return null;
		}

		public String getColumnText( Object element, int columnIndex )
		{
			// TODO Auto-generated method stub
			if ( columnIndex == 0 )
			{
				return (String) element;
			}
			return ""; //$NON-NLS-1$
		}

		public void addListener( ILabelProviderListener listener )
		{
			// TODO Auto-generated method stub

		}

		public void dispose( )
		{
			// TODO Auto-generated method stub

		}

		public boolean isLabelProperty( Object element, String property )
		{
			// TODO Auto-generated method stub
			return false;
		}

		public void removeListener( ILabelProviderListener listener )
		{
			// TODO Auto-generated method stub

		}
	};

	protected IStructuredContentProvider tableContentProvider = new IStructuredContentProvider( ) {

		public void dispose( )
		{
			// TODO Auto-generated method stub

		}

		public void inputChanged( Viewer viewer, Object oldInput,
				Object newInput )
		{
			// TODO Auto-generated method stub

		}

		public Object[] getElements( Object inputElement )
		{
			// TODO Auto-generated method stub
			if ( inputElement == null )
			{
				return new Object[0];
			}
			else if ( inputElement instanceof List )
			{
				return ( (List) inputElement ).toArray( );
			}
			return null;
		}
	};

	protected SelectionListener OpoertorSelection = new SelectionListener( ) {

		public void widgetSelected( SelectionEvent e )
		{
			// TODO Auto-generated method stub
			String value = getValueForOperator( operator.getText( ) );

			valueVisible = determineValueVisible( value );

			if ( valueVisible == 3 )
			{
				createValueListComposite( operator.getParent( ).getParent( ) );
				if(inputHandle != null )
				{
					if( inputHandle instanceof FilterCondition )
						valueList = new ArrayList( ((FilterCondition)inputHandle).getValue1List( ) );
					else
						valueList = new ArrayList( ((FilterConditionHandle)inputHandle).getValue1List( ));
				}
				for( int i = 0; i < valueList.size( ); i ++ )
				{
					if( valueList.get( i ) == null )
						valueList.remove( i );
				}
				tableViewer.setInput( valueList );
			}
			else
			{
				create2ValueComposite( operator.getParent( ).getParent( ) );
				if ( inputHandle != null )
				{
					if ( inputHandle instanceof FilterCondition )
					{
						value1.setText( DEUtil.resolveNull( ( (FilterCondition) inputHandle ).getValue1( ) ) );
						value2.setText( DEUtil.resolveNull( ( (FilterCondition) inputHandle ).getValue2( ) ) );
					}
					else
					{
						value1.setText( DEUtil.resolveNull( ( (FilterConditionHandle) inputHandle ).getValue1( ) ) );
						value2.setText( DEUtil.resolveNull( ( (FilterConditionHandle) inputHandle ).getValue2( ) ) );
					}
				}

			}

			if ( valueVisible == 0 )
			{
				value1.setVisible( true );
				valBuilder1.setVisible( true );
				value2.setVisible( true );
				valBuilder2.setVisible( true );
				
				value1.setEnabled( false );
				valBuilder1.setEnabled( false );
				value2.setEnabled( false );
				valBuilder2.setEnabled( false );
			}
			else if ( valueVisible == 1 )
			{
				value1.setVisible( true );
				valBuilder1.setVisible( true );
				value2.setVisible( true );
				valBuilder2.setVisible( true );
				
				value1.setEnabled( true );
				valBuilder1.setEnabled( true );
				value2.setEnabled( false );
				valBuilder2.setEnabled( false );
			}
			else if ( valueVisible == 2 )
			{
				value1.setVisible( true );
				valBuilder1.setVisible( true );
				value2.setVisible( true );
				valBuilder2.setVisible( true );
				
				value1.setEnabled( true );
				valBuilder1.setEnabled( true );
				value2.setEnabled( true );
				valBuilder2.setEnabled( true );
			}
			updateButtons( );
		}

		public void widgetDefaultSelected( SelectionEvent e )
		{
			// TODO Auto-generated method stub

		}
	};

	protected Listener ComboModify = new Listener( ) {

		public void handleEvent( Event e )
		{
			Combo combo = (Combo) e.widget;
			String newValue = combo.getText( );
			String value = getExpression( newValue );
			if ( value != null )
				newValue = value;
			combo.setText( newValue );
			updateButtons( );
		}
	};

	private String getExpression( String name )
	{
		for( int i = 0; i < this.dataSetColumns.length; i ++ )
		{
			if( this.dataSetColumns[i].equals( name ))
				return ExpressionUtil.createJSRowExpression( name );
		}
		return name;
	}
	
	protected Composite createDummy( Composite parent, int colSpan )
	{
		Composite dummy = new Composite( parent, SWT.NONE );
		GridData gdata = new GridData( GridData.VERTICAL_ALIGN_FILL );
		gdata.widthHint = 22;
		gdata.horizontalSpan = colSpan;
		gdata.heightHint = 10;
		dummy.setLayoutData( gdata );

		return dummy;
	}

	private Text createText( Composite parent )
	{
		Text txt = new Text( parent, SWT.BORDER );
		GridData gdata = new GridData( GridData.VERTICAL_ALIGN_FILL );
		gdata.widthHint = 100;
		txt.setLayoutData( gdata );

		return txt;
	}

	/*
	 * Update handle for the Map Rule builder
	 */
	public void updateHandle( FilterConditionHandle handle, int handleCount )
	{
		this.inputHandle = handle;
	}

	protected IExpressionProvider expressionProvider;

	public void setExpressionProvider( DesignElementHandle designHandle )
	{
		this.currentItem = ( DataSetHandle )designHandle;
		this.expressionProvider =  new DataSetExpressionProvider( designHandle );
	}

	/**
	 * Refreshes the OK button state.
	 * 
	 */
	protected void updateButtons( )
	{
		enableInput( isExpressionOK( ) );
		if ( getButton( IDialogConstants.OK_ID ) != null )
		{
			getButton( IDialogConstants.OK_ID ).setEnabled( isConditionOK( ) );
		}

	}

	protected void enableInput( boolean val )
	{
		if ( valueVisible == 0 )
		{
			value1.setVisible( true );
			valBuilder1.setVisible( true );
			value2.setVisible( true );
			valBuilder2.setVisible( true );
			value1.setEnabled( false );
			valBuilder1.setEnabled( false );
			value2.setEnabled( false );
			valBuilder2.setEnabled( false );
		}
		else if ( valueVisible == 1 )
		{
			value1.setVisible( true );
			value1.setEnabled( val );
			valBuilder1.setVisible( true );
			valBuilder1.setEnabled( val );
			value2.setVisible( true );
			value2.setEnabled( false );
			valBuilder2.setEnabled( false );
			valBuilder2.setVisible( true );
		}
		else if ( valueVisible == 2 )
		{
			value1.setVisible( true );
			valBuilder1.setVisible( true );
			value2.setVisible( true );
			valBuilder2.setVisible( true );
			value1.setEnabled( val );
			valBuilder1.setEnabled( val );
			value2.setEnabled( val );
			valBuilder2.setEnabled( val );
		}
		else if ( valueVisible == 3 )
		{
			valueListComposite.setEnabled( val );
			setControlEnable( valueListComposite, val );
			if(val)
			{
				checkAddButtonStatus( );
				checkEditDelButtonStatus( );
			}
		}
	}

	protected void setControlEnable( Control control, boolean bool )
	{
		if ( control == null || control.isDisposed( ) )
		{
			return;
		}
		control.setEnabled( bool );
		Composite tmp = null;
		if ( control instanceof Composite )
		{
			tmp = (Composite) control;
		}
		if ( tmp != null && tmp.getChildren( ) != null )
		{
			for ( int i = 0; i < tmp.getChildren( ).length; i++ )
			{
				setControlEnable( tmp.getChildren( )[i], bool );
			}
		}
	}

	/**
	 * Gets if the expression field is not empty.
	 */
	private boolean isExpressionOK( )
	{
		if ( expression == null )
		{
			return false;
		}

		if ( expression.getText( ) == null
				|| expression.getText( ).length( ) == 0 )
		{
			return false;
		}

		return true;
	}

	/**
	 * Gets if the condition is available.
	 */
	protected boolean isConditionOK( )
	{
		if ( expression == null )
		{
			return false;
		}

		if ( !isExpressionOK( ) )
		{
			return false;
		}

		return checkValues( );
	}

	/**
	 * Gets if the values of the condition is(are) available.
	 */
	private boolean checkValues( )
	{
		if(valueVisible == 3)
		{
			if(valueList.size( ) <= 0)
			{
				return false;
			}else
			{
				return true;
			}
		}else
		{
			assert(! value1.isDisposed( ));
			assert(! value2.isDisposed( ));
			
			if ( value1.getEnabled( ) )
			{
				if ( value1.getText( ) == null
						|| value1.getText( ).trim( ).length( ) == 0 )
				{
					return false;
				}
			}

			if (  value2.getEnabled( ) )
			{
				if ( value2.getText( ) == null
						|| value2.getText( ).trim( ).length( ) == 0 )
				{
					return false;
				}
			}
		}


		return true;
	}

	protected void checkAddButtonStatus( )
	{
		if ( addExpressionValue == null )
			return;
		String value = addExpressionValue.getValueText( ).getText( );
		if ( value == null || value.trim( ).length( ) == 0 )
		{
			addBtn.setEnabled( false );
			return;
		}
		if ( valueList.indexOf( value ) < 0 )
		{
			addBtn.setEnabled( true );
		}
		else
		{
			addBtn.setEnabled( false );
		}
	}

	protected void checkEditDelButtonStatus( )
	{
		if ( tableViewer == null )
			return;
		boolean enabled = ( tableViewer.getSelection( ) == null ) ? false
				: true;
		if ( enabled == true
				&& tableViewer.getSelection( ) instanceof StructuredSelection )
		{
			StructuredSelection selection = (StructuredSelection) tableViewer.getSelection( );
			if ( selection.toList( ).size( ) <= 0 )
			{
				enabled = false;
			}
		}
		editBtn.setEnabled( enabled );
		delBtn.setEnabled( enabled );
		
		enabled = table.getItemCount( ) > 0 ? true : false;
		delAllBtn.setEnabled( enabled );
		
	}

	/**
	 * SYNC the control value according to the handle.
	 */
	protected void syncViewProperties( )
	{
		FilterCondition fc = null;
		if( inputHandle instanceof FilterCondition)
			fc = (FilterCondition)inputHandle;
		else
			fc = (FilterCondition)((FilterConditionHandle)inputHandle).getStructure( );
		expression.setText( DEUtil.resolveNull( fc.getExpr( ) ) );
		operator.select( getIndexForOperatorValue( fc.getOperator( ) ) );
		valueVisible = determineValueVisible( fc.getOperator( ) );
		
		if ( valueVisible == 3 )
		{
			createValueListComposite( operator.getParent( ).getParent( ) );
			valueList = new ArrayList( fc.getValue1List( ) );
			tableViewer.setInput( valueList );
		}
		else
		{
			create2ValueComposite( operator.getParent( ).getParent( ) );
			value1.setText( DEUtil.resolveNull( fc.getValue1( ) ) );
			value2.setText( DEUtil.resolveNull( fc.getValue2( ) ) );
		}

		if ( valueVisible == 0 )
		{
			value1.setVisible( true );
			valBuilder1.setVisible( true );
			value2.setVisible( true );
			valBuilder2.setVisible( true );
			value1.setEnabled( false );
			valBuilder1.setEnabled( false );
			value2.setEnabled( false );
			valBuilder2.setEnabled( false );
		}
		else if ( valueVisible == 1 )
		{
			value1.setVisible( true );
			value1.setEnabled( true );
			valBuilder1.setVisible( true );
			valBuilder1.setEnabled( true );
			value2.setVisible( true );
			value2.setEnabled( false );
			valBuilder2.setEnabled( false );
			valBuilder2.setVisible( true );
		}
		else if ( valueVisible == 2 )
		{
			value1.setVisible( true );
			valBuilder1.setVisible( true );
			value2.setVisible( true );
			valBuilder2.setVisible( true );
			value1.setEnabled( true );
			valBuilder1.setEnabled( true );
			value2.setEnabled( true );
			valBuilder2.setEnabled( true );
		}
		else if ( valueVisible == 3 )
		{
			if ( expression.getText( ).length( ) == 0 )
			{
				valueListComposite.setEnabled( false );
			}
			else
			{
				valueListComposite.setEnabled( true );
			}
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.dialogs.Dialog#okPressed()
	 */
	protected void okPressed( )
	{
		try
		{
			if ( inputHandle instanceof FilterCondition )
			{
				FilterCondition filter = (FilterCondition) inputHandle;
				filter.setProperty( FilterCondition.OPERATOR_MEMBER,
						DEUtil.resolveNull( getValueForOperator( operator.getText( ) ) ) );
				if ( valueVisible == 3 )
				{
					filter.setValue1( valueList );
					filter.setValue2( "" ); //$NON-NLS-1$
				}
				else
				{
					assert ( !value1.isDisposed( ) );
					assert ( !value2.isDisposed( ) );
					filter.setValue1( DEUtil.resolveNull( value1.getText( ) ) );
					if ( value2.getVisible( ) )
					{
						filter.setValue2( DEUtil.resolveNull( value2.getText( ) ) );
					}
				}

				// set test expression for new map rule
				filter.setExpr( DEUtil.resolveNull( expression.getText( ) ) );
			}
			else
			{
				FilterConditionHandle handle = (FilterConditionHandle)inputHandle;
				handle.setOperator( DEUtil.resolveNull( getValueForOperator( operator.getText( ) ) ) );
				if ( valueVisible == 3 )
				{
					handle.setValue1( valueList );
					handle.setValue2( "" ); //$NON-NLS-1$
				}
				else
				{
					assert ( !value1.isDisposed( ) );
					assert ( !value2.isDisposed( ) );
					if ( value1.getVisible( ) )
					{
						handle.setValue1( DEUtil.resolveNull( value1.getText( ) ) );
					}
					else
					{
						handle.setValue1( "" ); //$NON-NLS-1$
					}

					if ( value2.getVisible( ) )
					{
						handle.setValue2( DEUtil.resolveNull( value2.getText( ) ) );
					}
					else
					{
						handle.setValue2( "" ); //$NON-NLS-1$
					}
				}
				handle.setExpr( DEUtil.resolveNull( expression.getText( ) ) );
			}
		}
		catch ( Exception e )
		{
			WidgetUtil.processError( getShell( ), e );
		}

		super.okPressed( );
	}

	protected void editValue( Control control )
	{
		String initValue = null;
		if ( control instanceof Text )
		{
			initValue = ( (Text) control ).getText( );
		}
		else if ( control instanceof Combo )
		{
			initValue = ( (Combo) control ).getText( );
		}
		ExpressionBuilder expressionBuilder = new ExpressionBuilder( getShell( ),
				initValue );

		expressionBuilder.setExpressionProvier( expressionProvider );

		if ( expressionBuilder.open( ) == OK )
		{
			String result = DEUtil.resolveNull( expressionBuilder.getResult( ) );
			if ( control instanceof Text )
			{
				( (Text) control ).setText( result );
			}
			else if ( control instanceof Combo )
			{
				( (Combo) control ).setText( result );
			}
		}
		updateButtons( );
	}

	private void refreshList( )
	{
		if ( refreshItems )
		{
			ArrayList finalItems = new ArrayList( 10 );
			for ( int n = 0; n < actions.length; n++ )
			{
				finalItems.add( actions[n] );
			}

			if ( currentItem != null )
			{
				// addParamterItems( finalItems );
			}
			popupItems = (String[]) finalItems.toArray( EMPTY_ARRAY );
		}
		refreshItems = false;
	}

	private List getSelectValueList( ) throws BirtException
	{
		return SelectValueFetcher.getSelectValueList( expression.getText( ), currentItem, false );
	}

	public int open( )
	{
		if ( getShell( ) == null )
		{
			// create the window
			create( );
		}
		updateButtons( );
		return super.open( );
	}

	private class ExpressionValue
	{

		Text valueText;
		Button btnPopup;

		Text getValueText( )
		{
			return valueText;
		}

		public void dispose( )
		{
			if ( isDisposed( ) )
			{
				return;
			}
			Composite container = valueText.getParent( );
			container.dispose( );

			valueText = null;
			btnPopup = null;
		}

		public boolean isDisposed( )
		{
			if ( valueText != null && !valueText.isDisposed( ) )
			{
				return false;
			}
			return true;
		}

		Button getPopupButton( )
		{
			return btnPopup;
		}

		/**
		 * Refresh the table viewer that applies for the multiple filter values
		 * 
		 */
		private void refreshTableViewer( )
		{
			if ( tableViewer != null
					&& addExpressionValue != null )
			{
				tableViewer.refresh( );
				updateButtons( );
				addExpressionValue.getValueText( )
						.setFocus( );
				addExpressionValue.getValueText( )
						.setText( "" ); //$NON-NLS-1$
			}
		}

		ExpressionValue( Composite parent, int style, final Combo expressionText )
		{
			Composite composite = ControlProvider.getDefaultComposite( parent );
			composite.setLayout( new ExpressionLayout() );
			valueText = createText( composite );
			valueText.addModifyListener( new ModifyListener( ) {

				public void modifyText( ModifyEvent e )
				{
					updateButtons( );
				}
			} );
			btnPopup = new Button( composite, SWT.ARROW | SWT.DOWN );
			
			btnPopup.addSelectionListener( new SelectionListener( ) {

				public void widgetSelected( SelectionEvent e )
				{
					refreshList( );
					
					Rectangle textBounds = valueText.getBounds( );
					Point pt = valueText.toDisplay( textBounds.x, textBounds.y );
					Rectangle rect = new Rectangle( pt.x,
							pt.y,
							valueText.getParent( ).getBounds( ).width,
							textBounds.height );

					PopupSelectionList popup = new PopupSelectionList( valueText.getParent( )
							.getShell( ) );
					popup.setItems( popupItems );
					String value = popup.open( rect );
					int selectionIndex = popup.getSelectionIndex( );

					boolean returnValue = false;
					if ( value != null )
					{
						String newValue[] = new String[1];
						if ( value.equals( ( actions[0] ) ) )
						{
							try
							{
								List selectValueList = getSelectValueList( );
								SelectValueDialog dialog = new SelectValueDialog( PlatformUI.getWorkbench( )
										.getDisplay( )
										.getActiveShell( ),
										Messages.getString( "ExpressionValueCellEditor.title" ) ); //$NON-NLS-1$
								dialog.setSelectedValueList( selectValueList );
								if ( valueListComposite != null
										&& valueListComposite.isEnabled( ) )
								{
									dialog.setMultipleSelection( true );
								}
								if ( bindingParams != null )
								{
									dialog.setBindingParams( bindingParams );
								}
								if ( dialog.open( ) == IDialogConstants.OK_ID )
								{
									returnValue = true;
									newValue = dialog.getSelectedExprValues( );
								}
							}
							catch ( Exception ex )
							{
								MessageDialog.openError( null,
										Messages.getString( "SelectValueDialog.selectValue" ), //$NON-NLS-1$
										Messages.getString( "SelectValueDialog.messages.error.selectVauleUnavailable" ) //$NON-NLS-1$
												+ "\n" + ex.getMessage( ) ); //$NON-NLS-1$
							}
						}
						else if ( value.equals( actions[1] ) )
						{
							ExpressionBuilder dialog = new ExpressionBuilder( PlatformUI.getWorkbench( )
									.getDisplay( )
									.getActiveShell( ),
									valueText.getText( ) );

							dialog.setExpressionProvier( expressionProvider );

							if ( dialog.open( ) == IDialogConstants.OK_ID )
							{
								returnValue = true;
								newValue[0] = dialog.getResult( );
							}
						}
						else if ( selectionIndex > 3 )
						{
							newValue[0] = "params[\"" + value + "\"]"; //$NON-NLS-1$ //$NON-NLS-2$
						}
						if ( returnValue )
						{
							if ( valueListComposite != null
									&& valueListComposite.isEnabled( ) )
							{
								boolean needsRefresh = false;
								for ( int i = 0; i < newValue.length; i++ )
								{
									if ( valueList.indexOf( DEUtil.resolveNull( newValue[i] ) ) < 0 )
									{
										valueList.add( DEUtil.resolveNull( newValue[i] ) );
										needsRefresh = true;
									}
								}
								if ( needsRefresh )
								{
									refreshTableViewer( );
								}
							}
							else
							{
								value = DEUtil.resolveNull( newValue[0] );
								if ( valueList.indexOf( value ) < 0 )
								{
									valueList.add( value );
									valueText.setText( value );
								}
							}
							if ( addBtn != null )
							{
								addBtn.setEnabled( false );
							}
						}
					}
				}

				public void widgetDefaultSelected( SelectionEvent e )
				{
					// TODO Auto-generated method stub

				}

			} );

		}

		private class ExpressionLayout extends Layout
		{

			public void layout( Composite editor, boolean force )
			{
				Rectangle bounds = editor.getClientArea( );
				Point size = btnPopup.computeSize( SWT.DEFAULT,
						SWT.DEFAULT,
						force );
				valueText.setBounds( 0, 0, bounds.width - size.x, bounds.height );
				btnPopup.setBounds( bounds.width - size.x,
						0,
						size.x,
						bounds.height );
			}

			public Point computeSize( Composite editor, int wHint, int hHint,
					boolean force )
			{
				if ( wHint != SWT.DEFAULT && hHint != SWT.DEFAULT )
					return new Point( wHint, hHint );
				Point contentsSize = valueText.computeSize( SWT.DEFAULT,
						SWT.DEFAULT,
						force );
				Point buttonSize = btnPopup.computeSize( SWT.DEFAULT,
						SWT.DEFAULT,
						force );
				// Just return the button width to ensure the button is not
				// clipped
				// if the label is long.
				// The label will just use whatever extra width there is
				Point result = new Point( buttonSize.x,
						Math.max( contentsSize.y, buttonSize.y ) );
				return result;
			}
		}
		

	}

	protected void createCustomControls( Composite parent )
	{
		UIUtil.bindHelp( parent,
				IHelpContextIds.INSERT_EDIT_FILTER_CONDITION_DIALOG_ID );

		
		
		applyDialogFont( parent );
				
		createFilterConditionContent( parent );
		
		
		
	}

	protected void rollback( )
	{
		// TODO Auto-generated method stub
		
	}

	protected IStatus validateSemantics( Object structureOrHandle )
	{
		// TODO Auto-generated method stub
		return null;
	}

	protected IStatus validateSyntax( Object structureOrHandle )
	{
		// TODO Auto-generated method stub
		return null;
	}

}