/*******************************************************************************
 * Copyright (c) 2006 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.refactoring;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
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.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.IWizardPage;

import org.eclipse.ui.PlatformUI;

import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;

import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;

import org.eclipse.jdt.internal.corext.refactoring.structure.HierarchyProcessor;
import org.eclipse.jdt.internal.corext.refactoring.structure.IMemberActionInfo;
import org.eclipse.jdt.internal.corext.refactoring.structure.PullUpRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.structure.PullUpRefactoringProcessor;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.JdtFlags;
import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.JavaElementLabelProvider;

import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
import org.eclipse.jdt.internal.ui.util.PixelConverter;
import org.eclipse.jdt.internal.ui.util.SWTUtil;
import org.eclipse.jdt.internal.ui.util.TableLayoutComposite;

/**
 * Wizard page for pull up refactoring wizards which allows to specify the
 * actions on the members to pull up.
 * 
 * @since 3.2
 */
public class PullUpMemberPage extends UserInputWizardPage {

	private class MemberActionCellModifier implements ICellModifier {

		public boolean canModify(final Object element, final String property) {
			if (!ACTION_PROPERTY.equals(property))
				return false;
			return ((MemberActionInfo) element).isEditable();
		}

		public Object getValue(final Object element, final String property) {
			if (!ACTION_PROPERTY.equals(property))
				return null;
			final MemberActionInfo info= (MemberActionInfo) element;
			return new Integer(info.getAction());
		}

		public void modify(final Object element, final String property, final Object value) {
			if (!ACTION_PROPERTY.equals(property))
				return;
			final int action= ((Integer) value).intValue();
			MemberActionInfo info;
			if (element instanceof Item) {
				info= (MemberActionInfo) ((Item) element).getData();
			} else
				info= (MemberActionInfo) element;
			if (!canModify(info, property))
				return;
			Assert.isTrue(info.isMethodInfo());
			info.setAction(action);
			updateWizardPage(null, true);
		}
	}

	private class MemberActionInfo implements IMemberActionInfo {

		private static final int NO_ACTION= 2;

		private int fAction;

		private final IMember fMember;

		public MemberActionInfo(final IMember member, final int action) {
			Assert.isTrue((member instanceof IMethod) || (member instanceof IField) || (member instanceof IType));
			assertAction(member, action);
			fMember= member;
			fAction= action;
		}

		private void assertAction(final IMember member, final int action) {
			if (member instanceof IMethod) {
				try {
					Assert.isTrue(action != DECLARE_ABSTRACT_ACTION || !JdtFlags.isStatic(member));
				} catch (JavaModelException e) {
					JavaPlugin.log(e);
				}
				Assert.isTrue(action == NO_ACTION || action == DECLARE_ABSTRACT_ACTION || action == PULL_UP_ACTION);
			} else {
				Assert.isTrue(action == NO_ACTION || action == PULL_UP_ACTION);
			}
		}

		public int getAction() {
			return fAction;
		}

		public String getActionLabel() {
			switch (fAction) {
				case PULL_UP_ACTION:
					return getPullUpActionLabel();
				case DECLARE_ABSTRACT_ACTION:
					return getDeclareAbstractActionLabel();
				case NO_ACTION:
					return ""; //$NON-NLS-1$
				default:
					Assert.isTrue(false);
					return null;
			}
		}

		public String[] getAllowedLabels() {
			if (isFieldInfo())
				return new String[] { ""}; //$NON-NLS-1$
			else if (isMethodInfo())
				return METHOD_LABELS;
			else if (isTypeInfo())
				return TYPE_LABELS;
			else {
				Assert.isTrue(false);
				return null;
			}
		}

		public IMember getMember() {
			return fMember;
		}

		public boolean isActive() {
			return getAction() != NO_ACTION;
		}

		public boolean isEditable() {
			if (fAction == NO_ACTION)
				return false;
			if (!isMethodInfo())
				return false;
			final IMethod method= (IMethod) fMember;
			try {
				return !JdtFlags.isStatic(method);
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
				return false;
			}
		}

		public boolean isFieldInfo() {
			return getMember() instanceof IField;
		}

		public boolean isMethodInfo() {
			return getMember() instanceof IMethod;
		}

		public boolean isTypeInfo() {
			return getMember() instanceof IType;
		}

		public void setAction(final int action) {
			assertAction(fMember, action);
			fAction= action;
		}
	}

	private static class MemberActionInfoLabelProvider extends LabelProvider implements ITableLabelProvider {

		private final ILabelProvider fLabelProvider= new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT | JavaElementLabelProvider.SHOW_SMALL_ICONS);

		public void dispose() {
			super.dispose();
			fLabelProvider.dispose();
		}

		public Image getColumnImage(final Object element, final int columnIndex) {
			final MemberActionInfo info= (MemberActionInfo) element;
			switch (columnIndex) {
				case MEMBER_COLUMN:
					return fLabelProvider.getImage(info.getMember());
				case ACTION_COLUMN:
					return null;
				default:
					Assert.isTrue(false);
					return null;
			}
		}

		public String getColumnText(final Object element, final int columnIndex) {
			final MemberActionInfo info= (MemberActionInfo) element;
			switch (columnIndex) {
				case MEMBER_COLUMN:
					return fLabelProvider.getText(info.getMember());
				case ACTION_COLUMN:
					return info.getActionLabel();
				default:
					Assert.isTrue(false);
					return null;
			}
		}
	}

	private static final int ACTION_COLUMN= 1;

	private static final String ACTION_PROPERTY= "action"; //$NON-NLS-1$	

	protected static final int DECLARE_ABSTRACT_ACTION= 1;

	private static final int MEMBER_COLUMN= 0;

	private static final String MEMBER_PROPERTY= "member"; //$NON-NLS-1$	

	protected static final int PULL_UP_ACTION= 0;

	private static final String SETTING_INSTANCEOF= "InstanceOf"; //$NON-NLS-1$

	private static final String SETTING_REPLACE= "Replace"; //$NON-NLS-1$

	private static int getEditableCount(final MemberActionInfo[] infos) {
		int result= 0;
		for (int i= 0; i < infos.length; i++) {
			final MemberActionInfo info= infos[i];
			if (info.isEditable())
				result++;
		}
		return result;
	}

	private static void putToStringMapping(final Map result, final String[] actionLabels, final int actionIndex) {
		result.put(actionLabels[actionIndex], new Integer(actionIndex));
	}

	private static void setActionForInfos(final MemberActionInfo[] infos, final int action) {
		for (int i= 0; i < infos.length; i++) {
			infos[i].setAction(action);
		}
	}

	private Button fAddButton;

	protected IType[] fCandidateTypes= {};

	private Button fCreateStubsButton;

	private Button fDeselectAllButton;

	private Button fEditButton;

	private Button fInstanceofButton;

	private Label fLabel;

	private Button fReplaceButton;

	private Button fSelectAllButton;

	private Label fStatusLine;

	protected final PullUpMethodPage fSuccessorPage;

	private Combo fSuperTypesCombo;

	private CheckboxTableViewer fTableViewer;

	protected final String[] METHOD_LABELS;

	protected final String[] TYPE_LABELS;

	public PullUpMemberPage(final String name, final PullUpMethodPage page) {
		super(name);
		fSuccessorPage= page;
		setDescription(RefactoringMessages.PullUpInputPage1_page_message);
		METHOD_LABELS= new String[2];
		METHOD_LABELS[PULL_UP_ACTION]= RefactoringMessages.PullUpInputPage1_pull_up;
		METHOD_LABELS[DECLARE_ABSTRACT_ACTION]= RefactoringMessages.PullUpInputPage1_declare_abstract;

		TYPE_LABELS= new String[1];
		TYPE_LABELS[PULL_UP_ACTION]= RefactoringMessages.PullUpInputPage1_pull_up;
	}

	private boolean areAllMembersMarkedAsPullUp() {
		return getMembersForAction(PULL_UP_ACTION).length == getTableInput().length;
	}

	protected boolean areAllMembersMarkedAsWithNoAction() {
		return getMembersForAction(MemberActionInfo.NO_ACTION).length == getTableInput().length;
	}

	private MemberActionInfo[] asMemberActionInfos() {
		final PullUpRefactoringProcessor processor= getPullUpRefactoring().getPullUpProcessor();
		final List toPullUp= Arrays.asList(processor.getMembersToMove());
		final IMember[] members= processor.getPullableMembersOfDeclaringType();
		final MemberActionInfo[] result= new MemberActionInfo[members.length];
		for (int i= 0; i < members.length; i++) {
			final IMember member= members[i];
			if (toPullUp.contains(member))
				result[i]= new MemberActionInfo(member, PULL_UP_ACTION);
			else
				result[i]= new MemberActionInfo(member, MemberActionInfo.NO_ACTION);
		}
		return result;
	}

	public boolean canFlipToNextPage() {
		if (getMethodsForAction(PULL_UP_ACTION).length == 0)
			return isPageComplete();
		return super.canFlipToNextPage();
	}

	private void checkAdditionalRequired() {
		try {
			PlatformUI.getWorkbench().getActiveWorkbenchWindow().run(false, false, new IRunnableWithProgress() {

				public void run(final IProgressMonitor pm) throws InvocationTargetException {
					try {
						checkPullUp(getPullUpRefactoring().getPullUpProcessor().getAdditionalRequiredMembersToPullUp(pm), true);
					} catch (JavaModelException e) {
						throw new InvocationTargetException(e);
					} finally {
						pm.done();
					}
				}
			});
		} catch (InvocationTargetException e) {
			ExceptionHandler.handle(e, getShell(), RefactoringMessages.PullUpInputPage_pull_Up, RefactoringMessages.PullUpInputPage_exception);
		} catch (InterruptedException e) {
			Assert.isTrue(false);
		}
	}

	protected void checkPageCompletionStatus(final boolean displayErrors) {
		if (areAllMembersMarkedAsWithNoAction()) {
			if (displayErrors)
				setErrorMessage(getNoMembersMessage());
			setPageComplete(false);
		} else {
			setErrorMessage(null);
			setPageComplete(true);
		}
		fSuccessorPage.fireSettingsChanged();
	}

	private void checkPullUp(final IMember[] elements, final boolean displayErrors) {
		setActionForMembers(elements, PULL_UP_ACTION);
		updateWizardPage(null, displayErrors);
	}

	private void createButtonComposite(final Composite parent) {
		final Composite composite= new Composite(parent, SWT.NONE);
		composite.setLayoutData(new GridData(GridData.FILL_VERTICAL));
		final GridLayout gl= new GridLayout();
		gl.marginHeight= 0;
		gl.marginWidth= 0;
		composite.setLayout(gl);

		fSelectAllButton= new Button(composite, SWT.PUSH);
		fSelectAllButton.setText(RefactoringMessages.PullUpWizard_select_all_label);
		fSelectAllButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		fSelectAllButton.setEnabled(true);
		SWTUtil.setButtonDimensionHint(fSelectAllButton);
		fSelectAllButton.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(final SelectionEvent event) {
				final IMember[] members= getMembers();
				setActionForMembers(members, PULL_UP_ACTION);
				updateWizardPage(null, true);
			}
		});

		fDeselectAllButton= new Button(composite, SWT.PUSH);
		fDeselectAllButton.setText(RefactoringMessages.PullUpWizard_deselect_all_label);
		fDeselectAllButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		fDeselectAllButton.setEnabled(false);
		SWTUtil.setButtonDimensionHint(fDeselectAllButton);
		fDeselectAllButton.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(final SelectionEvent event) {
				final IMember[] members= getMembers();
				setActionForMembers(members, MemberActionInfo.NO_ACTION);
				updateWizardPage(null, true);
			}
		});

		fEditButton= new Button(composite, SWT.PUSH);
		fEditButton.setText(RefactoringMessages.PullUpInputPage1_Edit);

		final GridData data= new GridData(GridData.FILL_HORIZONTAL);
		data.verticalIndent= new PixelConverter(parent).convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
		fEditButton.setLayoutData(data);
		fEditButton.setEnabled(false);
		SWTUtil.setButtonDimensionHint(fEditButton);
		fEditButton.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(final SelectionEvent event) {
				editSelectedMembers();
			}
		});

		fAddButton= new Button(composite, SWT.PUSH);
		fAddButton.setText(RefactoringMessages.PullUpInputPage1_Add_Required);
		fAddButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		SWTUtil.setButtonDimensionHint(fAddButton);
		fAddButton.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(final SelectionEvent event) {
				checkAdditionalRequired();
			}
		});
	}

	public void createControl(final Composite parent) {
		final Composite composite= new Composite(parent, SWT.NONE);
		final GridLayout layout= new GridLayout();
		layout.numColumns= 2;
		composite.setLayout(layout);

		createSuperTypeControl(composite);
		createSpacer(composite);
		createSuperTypeCheckbox(composite);
		createInstanceOfCheckbox(composite, layout.marginWidth);
		createStubCheckbox(composite);
		createSpacer(composite);
		createMemberTableLabel(composite);
		createMemberTableComposite(composite);
		createStatusLine(composite);

		setControl(composite);
		Dialog.applyDialogFont(composite);
		initializeEnablement();
		initializeCheckboxes();
		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IJavaHelpContextIds.PULL_UP_WIZARD_PAGE);
	}

	protected void createInstanceOfCheckbox(final Composite result, final int margin) {
		final HierarchyProcessor processor= getPullUpRefactoring().getPullUpProcessor();
		fInstanceofButton= new Button(result, SWT.CHECK);
		fInstanceofButton.setSelection(false);
		final GridData gd= new GridData();
		gd.horizontalIndent= (margin + fInstanceofButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).x);
		gd.horizontalSpan= 2;
		fInstanceofButton.setLayoutData(gd);
		fInstanceofButton.setText(getInstanceofButtonLabel());
		processor.setInstanceOf(fInstanceofButton.getSelection());
		fInstanceofButton.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(final SelectionEvent e) {
				processor.setInstanceOf(fInstanceofButton.getSelection());
			}
		});
		fReplaceButton.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(final SelectionEvent e) {
				fInstanceofButton.setEnabled(fReplaceButton.getSelection());
			}
		});
	}

	private void createMemberTable(final Composite parent) {
		final TableLayoutComposite layouter= new TableLayoutComposite(parent, SWT.NONE);
		layouter.addColumnData(new ColumnWeightData(60, true));
		layouter.addColumnData(new ColumnWeightData(40, true));

		final Table table= new Table(layouter, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.CHECK);
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		final GridData gd= new GridData(GridData.FILL_BOTH);
		gd.heightHint= SWTUtil.getTableHeightHint(table, getTableRowCount());
		gd.widthHint= convertWidthInCharsToPixels(30);
		layouter.setLayoutData(gd);

		final TableLayout tableLayout= new TableLayout();
		table.setLayout(tableLayout);

		final TableColumn column0= new TableColumn(table, SWT.NONE);
		column0.setText(RefactoringMessages.PullUpInputPage1_Member);

		final TableColumn column1= new TableColumn(table, SWT.NONE);
		column1.setText(RefactoringMessages.PullUpInputPage1_Action);

		fTableViewer= new PullPushCheckboxTableViewer(table);
		fTableViewer.setUseHashlookup(true);
		fTableViewer.setContentProvider(new ArrayContentProvider());
		fTableViewer.setLabelProvider(new MemberActionInfoLabelProvider());
		fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {

			public void selectionChanged(final SelectionChangedEvent event) {
				updateButtonEnablement(event.getSelection());
			}
		});
		fTableViewer.addCheckStateListener(new ICheckStateListener() {

			public void checkStateChanged(final CheckStateChangedEvent event) {
				final boolean checked= event.getChecked();
				final MemberActionInfo info= (MemberActionInfo) event.getElement();
				if (checked)
					info.setAction(PULL_UP_ACTION);
				else
					info.setAction(MemberActionInfo.NO_ACTION);
				updateWizardPage(null, true);
			}
		});
		fTableViewer.addDoubleClickListener(new IDoubleClickListener() {

			public void doubleClick(final DoubleClickEvent event) {
				editSelectedMembers();
			}
		});

		setTableInput();
		checkPullUp(getPullUpRefactoring().getPullUpProcessor().getMembersToMove(), false);
		setupCellEditors(table);
	}

	protected void createMemberTableComposite(final Composite parent) {
		final Composite composite= new Composite(parent, SWT.NONE);
		final GridData data= new GridData(GridData.FILL_BOTH);
		data.horizontalSpan= 2;
		composite.setLayoutData(data);
		final GridLayout layout= new GridLayout();
		layout.numColumns= 2;
		layout.marginWidth= 0;
		layout.marginHeight= 0;
		composite.setLayout(layout);

		createMemberTable(composite);
		createButtonComposite(composite);
	}

	protected void createMemberTableLabel(final Composite parent) {
		fLabel= new Label(parent, SWT.NONE);
		fLabel.setText(RefactoringMessages.PullUpInputPage1_Specify_actions);
		final GridData data= new GridData();
		data.horizontalSpan= 2;
		fLabel.setLayoutData(data);
	}

	protected void createSpacer(final Composite parent) {
		final Label label= new Label(parent, SWT.NONE);
		final GridData data= new GridData();
		data.horizontalSpan= 2;
		data.heightHint= convertHeightInCharsToPixels(1) / 2;
		label.setLayoutData(data);
	}

	protected void createStatusLine(final Composite composite) {
		fStatusLine= new Label(composite, SWT.NONE);
		final GridData data= new GridData();
		data.horizontalSpan= 2;
		updateStatusLine();
		fStatusLine.setLayoutData(data);
	}

	// String -> Integer
	private Map createStringMappingForSelectedMembers() {
		final Map result= new HashMap();
		putToStringMapping(result, METHOD_LABELS, PULL_UP_ACTION);
		putToStringMapping(result, METHOD_LABELS, DECLARE_ABSTRACT_ACTION);
		return result;
	}

	protected void createStubCheckbox(final Composite parent) {
		fCreateStubsButton= new Button(parent, SWT.CHECK);
		fCreateStubsButton.setText(getCreateStubsButtonLabel());
		final GridData data= new GridData();
		data.horizontalSpan= 2;
		fCreateStubsButton.setLayoutData(data);
		fCreateStubsButton.setEnabled(false);
		fCreateStubsButton.setSelection(getPullUpRefactoring().getPullUpProcessor().getCreateMethodStubs());
	}

	protected void createSuperTypeCheckbox(final Composite parent) {
		fReplaceButton= new Button(parent, SWT.CHECK);
		fReplaceButton.setText(getReplaceButtonLabel());
		final GridData data= new GridData();
		data.horizontalSpan= 2;
		fReplaceButton.setLayoutData(data);
		fReplaceButton.setEnabled(true);
		fReplaceButton.setSelection(getPullUpRefactoring().getPullUpProcessor().isReplace());
	}

	private void createSuperTypeCombo(final IProgressMonitor pm, final Composite parent) throws JavaModelException {
		final Label label= new Label(parent, SWT.NONE);
		label.setText(RefactoringMessages.PullUpInputPage1_Select_destination);
		label.setLayoutData(new GridData());

		fSuperTypesCombo= new Combo(parent, SWT.READ_ONLY);
		fCandidateTypes= getPullUpRefactoring().getPullUpProcessor().getCandidateTypes(new RefactoringStatus(), pm);
		if (fCandidateTypes.length > 0) {
			for (int i= 0; i < fCandidateTypes.length; i++) {
				final String comboLabel= JavaModelUtil.getFullyQualifiedName(fCandidateTypes[i]);
				fSuperTypesCombo.add(comboLabel);
			}
			fSuperTypesCombo.select(fCandidateTypes.length - 1);
			fSuperTypesCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		}
	}

	protected void createSuperTypeControl(final Composite parent) {
		try {
			PlatformUI.getWorkbench().getActiveWorkbenchWindow().run(false, false, new IRunnableWithProgress() {

				public void run(final IProgressMonitor monitor) throws InvocationTargetException {
					try {
						createSuperTypeCombo(monitor, parent);
					} catch (JavaModelException exception) {
						throw new InvocationTargetException(exception);
					} finally {
						monitor.done();
					}
				}
			});
		} catch (InvocationTargetException exception) {
			ExceptionHandler.handle(exception, getShell(), RefactoringMessages.PullUpInputPage_pull_Up, RefactoringMessages.PullUpInputPage_exception);
		} catch (InterruptedException exception) {
			Assert.isTrue(false);
		}
	}

	public void dispose() {
		fInstanceofButton= null;
		fReplaceButton= null;
		fTableViewer= null;
		super.dispose();
	}

	private void editSelectedMembers() {
		if (!fEditButton.isEnabled())
			return;

		final ISelection preserved= fTableViewer.getSelection();
		try {
			final String shellTitle= RefactoringMessages.PullUpInputPage1_Edit_members;
			final String labelText= RefactoringMessages.PullUpInputPage1_Mark_selected_members;
			final Map stringMapping= createStringMappingForSelectedMembers();
			final String[] keys= (String[]) stringMapping.keySet().toArray(new String[stringMapping.keySet().size()]);
			Arrays.sort(keys);
			final int initialSelectionIndex= getInitialSelectionIndexForEditDialog(stringMapping, keys);
			final ComboSelectionDialog dialog= new ComboSelectionDialog(getShell(), shellTitle, labelText, keys, initialSelectionIndex);
			dialog.setBlockOnOpen(true);
			if (dialog.open() == Window.CANCEL)
				return;
			final int action= ((Integer) stringMapping.get(dialog.getSelectedString())).intValue();
			setActionForInfos(getSelectedMembers(), action);
		} finally {
			updateWizardPage(preserved, true);
		}
	}

	private boolean enableEditButton(final IStructuredSelection ss) {
		if (ss.isEmpty() || ss.size() == 0)
			return false;
		return ss.size() == getEditableCount(getSelectedMembers());
	}

	private MemberActionInfo[] getActiveInfos() {
		final MemberActionInfo[] infos= getTableInput();
		final List result= new ArrayList(infos.length);
		for (int i= 0; i < infos.length; i++) {
			final MemberActionInfo info= infos[i];
			if (info.isActive())
				result.add(info);
		}
		return (MemberActionInfo[]) result.toArray(new MemberActionInfo[result.size()]);
	}

	private int getCommonActionCodeForSelectedInfos() {
		final MemberActionInfo[] infos= getSelectedMembers();
		if (infos.length == 0)
			return -1;

		final int code= infos[0].getAction();
		for (int i= 0; i < infos.length; i++) {
			if (code != infos[i].getAction())
				return -1;
		}
		return code;
	}

	protected String getCreateStubsButtonLabel() {
		return RefactoringMessages.PullUpInputPage1_Create_stubs;
	}

	protected String getDeclareAbstractActionLabel() {
		return RefactoringMessages.PullUpInputPage1_declare_abstract;
	}

	public IType getDestinationType() {
		final int index= fSuperTypesCombo.getSelectionIndex();
		if (index >= 0)
			return fCandidateTypes[index];
		return null;
	}

	private int getInitialSelectionIndexForEditDialog(final Map stringMapping, final String[] keys) {
		final int commonActionCode= getCommonActionCodeForSelectedInfos();
		if (commonActionCode == -1)
			return 0;
		for (final Iterator iter= stringMapping.keySet().iterator(); iter.hasNext();) {
			final String key= (String) iter.next();
			final int action= ((Integer) stringMapping.get(key)).intValue();
			if (commonActionCode == action) {
				for (int i= 0; i < keys.length; i++) {
					if (key.equals(keys[i]))
						return i;
				}
				Assert.isTrue(false);
			}
		}
		return 0;
	}

	protected String getInstanceofButtonLabel() {
		return RefactoringMessages.PullUpInputPage1_label_use_in_instanceof;
	}

	private IMember[] getMembers() {
		final MemberActionInfo[] infos= getTableInput();
		final List result= new ArrayList(infos.length);
		for (int index= 0; index < infos.length; index++) {
			result.add(infos[index].getMember());
		}
		return (IMember[]) result.toArray(new IMember[result.size()]);
	}

	private IMember[] getMembersForAction(final int action) {
		final MemberActionInfo[] infos= getTableInput();
		final List result= new ArrayList(infos.length);
		for (int index= 0; index < infos.length; index++) {
			if (infos[index].getAction() == action)
				result.add(infos[index].getMember());
		}
		return (IMember[]) result.toArray(new IMember[result.size()]);
	}

	private IMethod[] getMethodsForAction(final int action) {
		final MemberActionInfo[] infos= getTableInput();
		final List list= new ArrayList(infos.length);
		for (int index= 0; index < infos.length; index++) {
			if (infos[index].isMethodInfo() && infos[index].getAction() == action) {
				list.add(infos[index].getMember());
			}
		}
		return (IMethod[]) list.toArray(new IMethod[list.size()]);
	}

	public IWizardPage getNextPage() {
		initializeRefactoring();
		storeDialogSettings();
		if (getMethodsForAction(PULL_UP_ACTION).length == 0)
			return computeSuccessorPage();

		return super.getNextPage();
	}

	protected String getNoMembersMessage() {
		return RefactoringMessages.PullUpInputPage1_Select_members_to_pull_up;
	}

	protected String getPullUpActionLabel() {
		return RefactoringMessages.PullUpInputPage1_pull_up;
	}

	private PullUpRefactoring getPullUpRefactoring() {
		return (PullUpRefactoring) getRefactoring();
	}

	protected String getReplaceButtonLabel() {
		return RefactoringMessages.PullUpInputPage1_label_use_destination;
	}

	private MemberActionInfo[] getSelectedMembers() {
		Assert.isTrue(fTableViewer.getSelection() instanceof IStructuredSelection);
		final IStructuredSelection structured= (IStructuredSelection) fTableViewer.getSelection();
		final List result= structured.toList();
		return (MemberActionInfo[]) result.toArray(new MemberActionInfo[result.size()]);
	}

	private MemberActionInfo[] getTableInput() {
		return (MemberActionInfo[]) fTableViewer.getInput();
	}

	protected int getTableRowCount() {
		return 10;
	}

	private void initializeCheckBox(final Button checkbox, final String property, final boolean def) {
		final String s= JavaPlugin.getDefault().getDialogSettings().get(property);
		if (s != null)
			checkbox.setSelection(new Boolean(s).booleanValue());
		else
			checkbox.setSelection(def);
	}

	protected void initializeCheckboxes() {
		initializeCheckBox(fReplaceButton, SETTING_REPLACE, true);
		initializeCheckBox(fInstanceofButton, SETTING_INSTANCEOF, false);
	}

	protected void initializeEnablement() {
		MemberActionInfo[] infos= asMemberActionInfos();
		final boolean enabled= infos.length > 0;
		fTableViewer.getTable().setEnabled(enabled);
		fStatusLine.setEnabled(enabled);
		fAddButton.setEnabled(enabled);
		fLabel.setEnabled(enabled);
	}

	private void initializeRefactoring() {
		final PullUpRefactoringProcessor processor= getPullUpRefactoring().getPullUpProcessor();
		processor.setMembersToMove(getMembersForAction(PULL_UP_ACTION));
		processor.setAbstractMethods(getMethodsForAction(DECLARE_ABSTRACT_ACTION));
		final IType destination= getDestinationType();
		if (destination != null)
			processor.setDestinationType(destination);
		processor.setCreateMethodStubs(fCreateStubsButton.getSelection());
		processor.setReplace(fReplaceButton.getSelection());
		processor.setInstanceOf(fInstanceofButton.getSelection());
		processor.setDeletedMethods(getMethodsForAction(PULL_UP_ACTION));
	}

	protected boolean performFinish() {
		initializeRefactoring();
		storeDialogSettings();
		return super.performFinish();
	}

	private void setActionForMembers(final IMember[] members, final int action) {
		final MemberActionInfo[] infos= getTableInput();
		for (int i= 0; i < members.length; i++) {
			for (int j= 0; j < infos.length; j++) {
				if (infos[j].getMember().equals(members[i]))
					infos[j].setAction(action);
			}
		}
	}

	private void setTableInput() {
		fTableViewer.setInput(asMemberActionInfos());
	}

	private void setupCellEditors(final Table table) {
		final ComboBoxCellEditor editor= new ComboBoxCellEditor();
		editor.setStyle(SWT.READ_ONLY);
		fTableViewer.setCellEditors(new CellEditor[] { null, editor});
		fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {

			public void selectionChanged(final SelectionChangedEvent event) {
				if (editor.getControl() == null & !table.isDisposed())
					editor.create(table);
				final ISelection sel= event.getSelection();
				if (!(sel instanceof IStructuredSelection))
					return;
				final IStructuredSelection structured= (IStructuredSelection) sel;
				if (structured.size() != 1)
					return;
				final MemberActionInfo info= (MemberActionInfo) structured.getFirstElement();
				editor.setItems(info.getAllowedLabels());
				editor.setValue(new Integer(info.getAction()));
			}
		});

		final ICellModifier cellModifier= new MemberActionCellModifier();
		fTableViewer.setCellModifier(cellModifier);
		fTableViewer.setColumnProperties(new String[] { MEMBER_PROPERTY, ACTION_PROPERTY});
	}

	public void setVisible(final boolean visible) {
		super.setVisible(visible);
		if (visible) {
			try {
				getPullUpRefactoring().getPullUpProcessor().resetEnvironment();
			} finally {
				fTableViewer.setSelection(new StructuredSelection(getActiveInfos()), true);
				fTableViewer.getControl().setFocus();
			}
		}
	}

	private void storeDialogSettings() {
		final IDialogSettings settings= JavaPlugin.getDefault().getDialogSettings();
		settings.put(SETTING_REPLACE, fReplaceButton.getSelection());
		settings.put(SETTING_INSTANCEOF, fInstanceofButton.getSelection());
	}

	private void updateButtonEnablement(final ISelection selection) {
		if (fEditButton != null)
			fEditButton.setEnabled(enableEditButton((IStructuredSelection) selection));
		fCreateStubsButton.setEnabled(getMethodsForAction(DECLARE_ABSTRACT_ACTION).length != 0);
		fInstanceofButton.setEnabled(fReplaceButton.getSelection());
		if (fSelectAllButton != null)
			fSelectAllButton.setEnabled(!areAllMembersMarkedAsPullUp());
		if (fDeselectAllButton != null)
			fDeselectAllButton.setEnabled(!areAllMembersMarkedAsWithNoAction());
	}

	private void updateStatusLine() {
		if (fStatusLine == null)
			return;
		final int selected= fTableViewer.getCheckedElements().length;
		final String[] keys= { String.valueOf(selected)};
		final String msg= Messages.format(RefactoringMessages.PullUpInputPage1_status_line, keys);
		fStatusLine.setText(msg);
	}

	private void updateWizardPage(final ISelection selection, final boolean displayErrors) {
		fTableViewer.refresh();
		if (selection != null) {
			fTableViewer.getControl().setFocus();
			fTableViewer.setSelection(selection);
		}
		checkPageCompletionStatus(displayErrors);
		updateButtonEnablement(fTableViewer.getSelection());
		updateStatusLine();
	}
}